Creación del Dataframe
Creando el DataFrame a partir de la variable Ingresos Totales
(IT)
ITS <- filter(ITS, Año %in% c("2020","2021","2022"))
ITS %>% group_by(Año,Mes,Aeropuerto,Infraestructura) %>% summarise(IT = sum(`Importe por Servicios`)) -> DF
Importante: Se toma en cuenta que al un aeropuerto no declarar un
importe de servicios por un tipo de rubro como el alquiler de
espacios publicitarios, los ingresos en este rubro serán 0.
Para esto crearemos una variable conjunta al rubro de importe que
verificará si este ha sido declarado o no, se identificará con el nombre
de la variable y un sufijo “_VER”. Pese a que esta operación genera
sesgo, al tener un sentido con la realidad se considera que no es
significativo.
Uniendo la variable Numero de Pasajeros Internacionales (NPI)
PI <- filter(TP, `Tipo de Pasajero` == "INTERNACIONAL")
PI <- filter(PI,Año %in% c(2020,2021,2022))
PI <- select(PI, -Periodo)
PI <- select(PI, -`Tipo de Pasajero`)
DF <- merge(DF,PI, by = c("Año","Mes","Aeropuerto","Infraestructura"), all = TRUE)
DF <- rename(DF, "NPI" = "Nro Pasajeros")
DF$NPI[is.na(DF$NPI)] <- 0
#Reemplazo de N/A's por 0
Uniendo la variable Numero de Pasajeros Nacionales (NPN)
PN <- filter(TP, `Tipo de Pasajero` == "NACIONAL")
PN <- filter(PN,Año %in% c(2020,2021,2022))
PN <- select(PN, -Periodo)
PN <- select(PN, -`Tipo de Pasajero`)
DF <- merge(DF,PN, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "NPN" = "Nro Pasajeros")
DF$NPN[is.na(DF$NPN)] <- 0
#Reemplazo de N/A's por 0
Uniendo la variable Ingreso Rubro T U U A NACIONAL (TUUAN)
TUUAN <- filter(ITS, `Rubro Ingreso` == "T U U A NACIONAL")
TUUAN <- filter(TUUAN,Año %in% c(2020,2021,2022))
TUUAN <- select(TUUAN, -'Tipo Ingreso')
TUUAN <- select(TUUAN, -'Rubro Ingreso')
TUUAN <- select(TUUAN, -'Periodo')
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, TUUAN, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "TUUAN_VER" = "Importe por Servicios")
DF <- merge(DF, TUUAN, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "TUUAN" = "Importe por Servicios")
DF$TUUAN_VER[is.na(DF$TUUAN_VER)] <- 0
DF$TUUAN_VER[DF$TUUAN_VER != 0] <- "Si"
DF$TUUAN_VER[DF$TUUAN_VER == "0"] <- "No"
DF$TUUAN[is.na(DF$TUUAN)] <- 0
#Reemplazo de N/A's por 0
Uniendo la variable Ingreso Rubro T U U A INTERNACIONAL (TUUAI)
TUUAI <- filter(ITS, `Rubro Ingreso` == "T U U A INTERNACIONAL")
TUUAI <- filter(TUUAI,Año %in% c(2020,2021,2022))
TUUAI <- select(TUUAI, -'Tipo Ingreso')
TUUAI <- select(TUUAI, -'Rubro Ingreso')
TUUAI <- select(TUUAI, -'Periodo')
DF <- merge(DF, TUUAI, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "TUUAI_VER" = "Importe por Servicios")#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, TUUAI, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "TUUAI" = "Importe por Servicios")
DF$TUUAI_VER[is.na(DF$TUUAI_VER)] <- 0
DF$TUUAI_VER[DF$TUUAI_VER != 0] <- "Si"
DF$TUUAI_VER[DF$TUUAI_VER == "0"] <- "No"
DF$TUUAI[is.na(DF$TUUAI)] <- 0
#Reemplazo de N/A's por 0
Uniendo la variable Ingreso Rubro ATERRIZAJE Y DESPEGUE (IRAD)
IRAD <- filter(ITS, `Rubro Ingreso` == "ATERRIZAJE Y DESPEGUE")
IRAD <- filter(IRAD,Año %in% c(2020,2021,2022))
IRAD <- select(IRAD, -'Tipo Ingreso')
IRAD <- select(IRAD, -'Rubro Ingreso')
IRAD <- select(IRAD, -'Periodo')
DF <- merge(DF, IRAD, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IRAD_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, IRAD, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IRAD" = "Importe por Servicios")
DF$IRAD_VER[is.na(DF$IRAD_VER)] <- 0
DF$IRAD_VER[DF$IRAD_VER != 0] <- "Si"
DF$IRAD_VER[DF$IRAD_VER == "0"] <- "No"
DF$IRAD[is.na(DF$IRAD)] <- 0
#Reemplazo de N/A's por 0
Uniendo la variable Ingreso Rubro ALQUILER AREAS DE MANTENIMIENTO
(AADM)
AADM <- filter(ITS, `Rubro Ingreso` == "ALQUILER AREAS DE MANTENIMIENTO")
AADM <- filter(AADM,Año %in% c(2020,2021,2022))
AADM <- select(AADM, -'Tipo Ingreso')
AADM <- select(AADM, -'Rubro Ingreso')
AADM <- select(AADM, -'Periodo')
DF <- merge(DF, AADM, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "AADM_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, AADM, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "AADM" = "Importe por Servicios")
DF$AADM_VER[is.na(DF$AADM_VER)] <- 0
DF$AADM_VER[DF$AADM_VER != 0] <- "Si"
DF$AADM_VER[DF$AADM_VER == "0"] <- "No"
DF$AADM[is.na(DF$AADM)] <- 0
#Reemplazo de N/A's por 0
Uniendo la variable Ingreso ALQUILER DE ESPACIOS PUBLICITARIOS
(ADEP)
ADEP <- filter(ITS, `Rubro Ingreso` == "ALQUILER DE ESPACIOS PUBLICITARIOS")
ADEP <- filter(ADEP,Año %in% c(2020,2021,2022))
ADEP <- select(ADEP, -'Tipo Ingreso')
ADEP <- select(ADEP, -'Rubro Ingreso')
ADEP <- select(ADEP, -'Periodo')
DF <- merge(DF, ADEP, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "ADEP_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, ADEP, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "ADEP" = "Importe por Servicios")
DF$ADEP_VER[is.na(DF$ADEP_VER)] <- 0
DF$ADEP_VER[DF$ADEP_VER != 0] <- "Si"
DF$ADEP_VER[DF$ADEP_VER == "0"] <- "No"
DF$ADEP[is.na(DF$ADEP)] <- 0
#Reemplazo de N/A's por 0
Uniendo la variable Ingreso ALQUILER LOCALES COMERCIALES (ALC)
ALC <- filter(ITS, `Rubro Ingreso` == "ALQUILER LOCALES COMERCIALES")
ALC <- filter(ALC,Año %in% c(2020,2021,2022))
ALC <- select(ALC, -'Tipo Ingreso')
ALC <- select(ALC, -'Rubro Ingreso')
ALC <- select(ALC, -'Periodo')
DF <- merge(DF, ALC, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "ALC_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, ALC, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "ALC" = "Importe por Servicios")
DF$ALC_VER[is.na(DF$ALC_VER)] <- 0
DF$ALC_VER[DF$ALC_VER != 0] <- "Si"
DF$ALC_VER[DF$ALC_VER == "0"] <- "No"
DF$ALC[is.na(DF$ALC)] <- 0
#Reemplazo de N/A's por 0
Uniendo la variable Ingreso Rubro ALQUILER OFICINAS OPERACIONES
AEROLÍNEAS (AOOA)
AOOA <- filter(ITS, `Rubro Ingreso` == "ALQUILER OFICINAS OPERACIONES AEROLÍNEAS")
AOOA <- filter(AOOA,Año %in% c(2020,2021,2022))
AOOA <- select(AOOA, -'Tipo Ingreso')
AOOA <- select(AOOA, -'Rubro Ingreso')
AOOA <- select(AOOA, -'Periodo')
DF <- merge(DF, AOOA, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "AOOA_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, AOOA, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "AOOA" = "Importe por Servicios")
DF$AOOA_VER[is.na(DF$AOOA_VER)] <- 0
DF$AOOA_VER[DF$AOOA_VER != 0] <- "Si"
DF$AOOA_VER[DF$AOOA_VER == "0"] <- "No"
DF$AOOA[is.na(DF$AOOA)] <- 0
Uniendo la variable Ingreso Rubro ALQUILERES DE ALMACEN/HANGAR
(ADAH)
ADAH <- filter(ITS, `Rubro Ingreso` == "ALQUILERES DE ALMACEN/HANGAR")
ADAH <- filter(ADAH,Año %in% c(2020,2021,2022))
ADAH <- select(ADAH, -'Tipo Ingreso')
ADAH <- select(ADAH, -'Rubro Ingreso')
ADAH <- select(ADAH, -'Periodo')
DF <- merge(DF, ADAH, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "ADAH_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, ADAH, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "ADAH" = "Importe por Servicios")
DF$ADAH_VER[is.na(DF$ADAH_VER)] <- 0
DF$ADAH_VER[DF$ADAH_VER != 0] <- "Si"
DF$ADAH_VER[DF$ADAH_VER == "0"] <- "No"
DF$ADAH[is.na(DF$ADAH)] <- 0
Uniendo la variable Ingreso Rubro ATENCIÓN EN HORAS EXTRAS (AEHE)
AEHE <- filter(ITS, `Rubro Ingreso` == "ATENCIÓN EN HORAS EXTRAS")
AEHE <- filter(AEHE,Año %in% c(2020,2021,2022))
AEHE <- select(AEHE, -'Tipo Ingreso')
AEHE <- select(AEHE, -'Rubro Ingreso')
AEHE <- select(AEHE, -'Periodo')
DF <- merge(DF, AEHE, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "AEHE_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, AEHE, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "AEHE" = "Importe por Servicios")
DF$AEHE_VER[is.na(DF$AEHE_VER)] <- 0
DF$AEHE_VER[DF$AEHE_VER != 0] <- "Si"
DF$AEHE_VER[DF$AEHE_VER == "0"] <- "No"
DF$AEHE[is.na(DF$AEHE)] <- 0
Uniendo la variable Ingreso Rubro ESTACIONAMIENTO AERONAVES
(IREA)
IREA <- filter(ITS, `Rubro Ingreso` == "ESTACIONAMIENTO AERONAVES")
IREA <- filter(IREA,Año %in% c(2020,2021,2022))
IREA <- select(IREA, -'Tipo Ingreso')
IREA <- select(IREA, -'Rubro Ingreso')
IREA <- select(IREA, -'Periodo')
DF <- merge(DF, IREA, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IREA_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, IREA, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IREA" = "Importe por Servicios")
DF$IREA_VER[is.na(DF$IREA_VER)] <- 0
DF$IREA_VER[DF$IREA_VER != 0] <- "Si"
DF$IREA_VER[DF$IREA_VER == "0"] <- "No"
DF$IREA[is.na(DF$IREA)] <- 0
Uniendo la variable Ingreso Rubro INGRESOS FINANCIEROS (IRIF)
IRIF <- filter(ITS, `Rubro Ingreso` == "INGRESOS FINANCIEROS")
IRIF <- filter(IRIF,Año %in% c(2020,2021,2022))
IRIF <- select(IRIF, -'Tipo Ingreso')
IRIF <- select(IRIF, -'Rubro Ingreso')
IRIF <- select(IRIF, -'Periodo')
DF <- merge(DF, IRIF, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IRIF_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, IRIF, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IRIF" = "Importe por Servicios")
DF$IRIF_VER[is.na(DF$IRIF_VER)] <- 0
DF$IRIF_VER[DF$IRIF_VER != 0] <- "Si"
DF$IRIF_VER[DF$IRIF_VER == "0"] <- "No"
DF$IRIF[is.na(DF$IRIF)] <- 0
Uniendo la variable Ingreso Rubro REEMBOLSOS (IRR)
IRR <- filter(ITS, `Rubro Ingreso` == "REEMBOLSOS")
IRR <- filter(IRR,Año %in% c(2020,2021,2022))
IRR <- select(IRR, -'Tipo Ingreso')
IRR <- select(IRR, -'Rubro Ingreso')
IRR <- select(IRR, -'Periodo')
IRR <- filter(IRR, `Importe por Servicios` != 0)
DF <- merge(DF, IRR, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IRR_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, IRR, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IRR" = "Importe por Servicios")
DF$IRR_VER[is.na(DF$IRR_VER)] <- 0
DF$IRR_VER[DF$IRR_VER != 0] <- "Si"
DF$IRR_VER[DF$IRR_VER == "0"] <- "No"
DF$IRR[is.na(DF$IRR)] <- 0
Creando la variable Numero de Pasajeros totales (NP)
DF %>% mutate(NP = NPN + NPI) -> DF
#Numero de pasajeros totales
Organizando el DF
DF$Mes = factor(DF$Mes, levels =c("Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Setiembre","Octubre","Noviembre","Diciembre"))
DF <- arrange(DF, Año, Mes)
Limpieza de datos
Se considera que en caso no se cuente con el nombre del aeropuerto o
su infraestructura (Siempre debe venir acompañada del nombre), la unidad
muestral no podrá entrar al análisis pues por ejemplo si nos dicen
cuanto gano un aeropuerto desconocido, esto no nos dirá nada y por ello
la eliminaremos.
DF$Aeropuerto[DF$Aeropuerto == 'No precisa'] <- NA
DF$Aeropuerto[DF$Aeropuerto == '-'] <- NA
DF$Infraestructura[DF$Infraestructura == '-'] <- NA
DF <- filter(DF, Infraestructura != is.na("Infraestructura") & Aeropuerto != is.na("Aeropuerto"))
Cambiamos los nombres de la variable Infraestructura:
DF %>% mutate("Infraestructura" =
ifelse(Infraestructura=="ADP", "Aeropuertos del Perú S.A.",
ifelse(Infraestructura=="AAP", "Aeropuertos Andinos del Perú S.A.",
ifelse(Infraestructura=="COR", "CORPAC S.A.",
ifelse(Infraestructura=="LAP", "Lima Airport Partners S.R.L.",Infraestructura))))) -> DF
Eliminamos las variables temporales:
rm(list = c("AADM","ADAH","ADEP","AEHE","ALC","AOOA","IRAD","IREA","IRIF","IRS","ITS","PI","PN","TP","TUUAI","TUUAN","IRR"))
Finalmente, eliminaremos aquellas observaciones donde existan NA’s.
Antes de hacer esto encontramos que la mayoría de aeropuertos de la
infraestructura “CORPAC S.A.” no ha reportado sus ingresos totales por
lo tanto estaríamos dejando fuera del análisis a estos aeropuertos.
DF <- drop_na(DF)
sum(complete.cases(DF))
Exportando la base de datos
write_csv(DF,"BaseLimpiav2.csv")
Descriptores Numéricos
cv <- function(x){
return(sd(x, na.rm=T)/mean(x, na.rm=T))
}
tabla <- data.frame(Variables = c('IT', 'NPN', 'NPI', 'TUUAN','TUUAI'),
Media = c(mean(DF$IT, na.rm=T),
mean(DF$NPN, na.rm = T),
mean(DF$NPI, na.rm= T),
mean(DF$TUUAN, na.rm= T),
mean(DF$TUUAI, na.rm= T)),
Mediana = c(median(DF$IT, na.rm=T),
median(DF$NPN, na.rm = T),
median(DF$NPI, na.rm= T),
median(DF$TUUAN, na.rm = T),
median(DF$TUUAI, na.rm= T)),
Desviacion = c(sd(DF$IT, na.rm=T),
sd(DF$NPN, na.rm = T),
sd(DF$NPI, na.rm= T),
sd(DF$TUUAN, na.rm = T),
sd(DF$TUUAI, na.rm= T)),
Varianza = c(var(DF$IT, na.rm = T),
var(DF$NPN, na.rm = T),
var(DF$NPI, na.rm = T),
var(DF$TUUAN, na.rm = T),
var(DF$TUUAI, na.rm = T)),
RangoIntercuartil = c(IQR(DF$IT, na.rm = T),
IQR(DF$NPN, na.rm = T),
IQR(DF$NPI, na.rm = T),
IQR(DF$TUUAN, na.rm = T),
IQR(DF$TUUAI, na.rm = T)),
CoeficienteVariacion = c(cv(DF$IT),
cv(DF$NPN),
cv(DF$NPI),
cv(DF$NPN),
cv(DF$NPI)))
tabla
De la tabla podemos conseguir la siguiente información:
La escala con la que se trabaja es bastante grande, de ahí el
hecho que la varianza y desviación sean tan grande.
Tanto la varianza como la desviación nos indican que los datos de
los Ingresos Totales, el Numero de Pasajeros Nacionales y el Numero de
Pasajeros Internacionales están muy dispersos.
Se aprecia un fenómeno que la mediana y el rango intercuartil de
la variable Pasajeros internacionales es 0. Esto quiere decir que hay
muchos aeropuertos los cuales no suelen recibir pasajeros
internacionales.
Objetivo 1
Se realizara el coeficiente de correlación entre cada variable rubro
y los ingresos totales, además se creará un modelo lineal que represente
las relaciones. Esto nos facilita el trabajar con las 12 variables y
poder sintetizar la información en un solo gráfico.
coefcor <- c(1:12)
# TUUAN
coefcor[1] <-cor(DF$IT, DF$TUUAN, use="complete.obs")
# TUUAI
coefcor[2] <-cor(DF$IT, DF$TUUAI, use="complete.obs")
# IRAD
coefcor[3] <-cor(DF$IT, DF$IRAD, use="complete.obs")
# AADM
coefcor[4] <-cor(DF$IT, DF$AADM, use="complete.obs")
# ADEP
coefcor[5] <-cor(DF$IT, DF$ADEP, use="complete.obs")
# ALC
coefcor[6] <-cor(DF$IT, DF$ALC, use="complete.obs")
# AOOA
coefcor[7] <-cor(DF$IT, DF$AOOA, use="complete.obs")
# ADAH
coefcor[8] <-cor(DF$IT, DF$ADAH, use="complete.obs")
# AEHE
coefcor[9] <-cor(DF$IT, DF$AEHE, use="complete.obs")
# IREA
coefcor[10] <-cor(DF$IT, DF$IREA, use="complete.obs")
# IRIF
coefcor[11] <-cor(DF$IT, DF$IRIF, use="complete.obs")
# IRR
coefcor[12] <-cor(DF$IT, DF$IRR, use="complete.obs")
Ahora se procederá a la revisión de los coeficientes de correlación,
si estos tienen un número mayor a 0.75 o menor a -0.75 se considerará
que tienen un modelo lineal válido.
coefcor
Se observa que los coeficientes de correlación con indices (4, 5, 6,
7, 8, 9, 11 y 12) no cumplen con el criterio requerido, es decir no
poseen una correlación lineal con la variable de ingresos totales, esto
también nos indica que sus datos se encuentran muy dispersos en
comparación con los datos de los ingresos totales.
Ahora se realizará y graficará los modelos lineales de la variables
que presentan buena correlación. Es importante notar que en todas estas
se tiene una correlación positiva, esto tiene sentido pues entre más
dinero haya de algún rubro, más dinero habrá en los ingresos totales
pendientes <- c(1:4)
interceptos <- c(1:4)
# TUUAN
modelo <- lm(DF$IT ~ DF$TUUAN, data=DF)
pendientes[1] <- as.numeric(modelo$coefficients[2])
interceptos[1] <- as.numeric(modelo$coefficients[1])
# TUUAI
modelo <- lm(DF$IT ~ DF$TUUAI, data=DF)
pendientes[2] <- as.numeric(modelo$coefficients[2])
interceptos[2] <- as.numeric(modelo$coefficients[1])
# IRAD
modelo <- lm(DF$IT ~ DF$IRAD, data=DF)
pendientes[3] <- as.numeric(modelo$coefficients[2])
interceptos[3] <- as.numeric(modelo$coefficients[1])
# IRIF
modelo <- lm(DF$IT ~ DF$IREA, data=DF)
pendientes[4] <- as.numeric(modelo$coefficients[2])
interceptos[4] <- as.numeric(modelo$coefficients[1])
fig <- plot_ly(DF, x = ~TUUAN, y = ~IT,
type = "scatter",
mode = "markers",
name="TUUAN",
marker = list(color = '#ef476f')
) %>%
add_trace(x = ~c(-interceptos[1]/pendientes[1],9000000), y = c(0,pendientes[1]*9000000+interceptos[1]),
type = "scatter",
mode = "lines",
name="TUUAN-model",
marker = list(color = '#ef476f')
) %>%
add_trace(DF, x = ~TUUAI, y = ~IT,
type = "scatter",
mode = "markers",
name="TUUAI",
marker = list(color = '#ffd166')
) %>%
add_trace(x = ~c(-interceptos[2]/pendientes[2],9000000), y = c(0,pendientes[2]*9000000+interceptos[2]),
type = "scatter",
mode = "lines",
name="TUUAI-model",
marker = list(color = '#ffd166')
) %>%
add_trace(DF, x = ~IRAD, y = ~IT,
type = "scatter",
mode = "markers",
name="IRAD",
marker = list(color = '#06d6a0')
) %>%
add_trace(x = ~c(-interceptos[3]/pendientes[3],9000000), y = c(0,pendientes[3]*9000000+interceptos[3]),
type = "scatter",
mode = "lines",
name="IRAD-model",
marker = list(color = '#06d6a0')
) %>%
add_trace(DF, x= ~IREA, y = ~IT,
type="scatter",
mode="markers",
name="IREA",
marker = list(color = '#118ab2')
) %>%
add_trace(x = ~c(-interceptos[4]/pendientes[4],9000000), y = c(0,pendientes[4]*9000000+interceptos[4]),
type="scatter",
mode="lines",
name="IREA-model",
marker = list(color = '#118ab2')
) %>%
layout(xaxis = list( title = "Ingresos US$"),
yaxis = list( title = "Ingresos totales US$"))
fig
Usando el gráfico interactivo podemos aislar cada uno de estos rubros
y ver su comportamiento junto a su modelo. Aquí vemos como el modelo de
IREA tiene la mayor pendiente significando que la mayor parte de los
ingresos totales en proporción vendría de este rubro, sin embargo,
observamos que la data no es congruente, el modelo no se aproxima
correctamente pese a que vimos que obtuvo un coeficiente de correlación
mayor a 0.75. Con esto se deja en evidencia que el coeficiente de
correlación lineal no es el único que debemos tomar en cuenta al
realizar un modelo de regresión lineal. Entonces, dejando de lado a
IREA, se aprecia que los modelos y la data de TUUAN, TUUAI e IRAD se
aproximan bastante bien, siendo, el de mayor pendiente, IRAD. Por lo que
concluimos que la mayor parte de los ingresos totales dependen de los
ingresos obtenidos por el importe de servicios de Aterizaje y
despegue.
Objetivo 2
plot(DF$IREA, DF$IT, xlab = "Numero de pasajeros (miles)", ylab = "Ingresos totales (millones de US$)", col="darkgreen", pch="•")
abline(a=interceptos[4], b= pendientes[4])
plot_ly(y =~ DF$IT, x =~DF$IREA, type="scatter") %>%
Numero de Pasajeros vs Ingresos Totales
plot(DF$NP/1000, DF$IT/1000000, xlab = "Numero de pasajeros (miles)", ylab = "Ingresos totales (millones de US$)", col="darkgreen", pch="•", xlim = c(0,2000))
Comenzamos comparando el numero de pasajeros en miles totales, suma
de pasajeros internacionales y nacionales, con los ingresos totales de
cada aeropuerto en determinado mes y año en millones de dolares. A
simple vista se puede ver un cierto tipo de relación lineal, sin embargo
tenemos que comprobarlo. Usaremos el coeficiente de correlación ya que
este no toma en cuenta la escala de las unidades, perfecto para nuestro
estudio.
cor(DF$IT, DF$NP, use="complete.obs")
Con la información suministrada del coeficiente de correlación se
deduce que la relación lineal entre el numero de pasajeros y los
ingresos totales es buena, casi perfecta y ascendente. Es decir los
ingresos totales aumentaran en cuanto aumente el numero de
pasajeros.
Ahora crearemos un modelo de regresión lineal.
modelo = lm(DF$IT ~ DF$NP, data=DF)
modelo
d <- data.frame("X"=DF$NP/1000, "Y"=DF$IT/1000000)
modelo = lm(d$Y ~ d$X, data=d)
modelo
Hemos creado dos modelos que en realidad son el mismo pero a
diferentes escalas. El primero nos sirve para usar directamente el
numero de pasajeros y los ingresos totales en dolares. El segundo para
usar el numero de pasajeros en miles y conseguir los ingresos totales en
millones de dolares. Ambos modelos nos permiten aproximar, predecir los
ingresos totales de un aeropuerto en determinado mes y año usando la
cantidad de pasajeros totales que llevo en el mismo lapso de tiempo.
plot(DF$NP/1000, DF$IT/1000000, xlab = "Numero de pasajeros (miles)", ylab = "Ingresos totales (millones de US$)", col="darkgreen", pch="•", xlim = c(0,2000))
abline(a= -0.14890, b=0.01646, col="green")
Numero de Pasajeros Nacionales e Internacionales vs Ingresos
Totales
par(mfrow=c(1,2))
plot(DF$NPN/1000, DF$IT/1000000, xlab = "Numero de pasajeros nacionales (miles)", ylab = "Ingresos totales (millones de US$)", col="red", pch="•")
plot(DF$NPI/1000, DF$IT/1000000, xlab = "Numero de pasajeros internacionales (miles)", ylab = "Ingresos totales (millones de US$)", col="blue", pch="•")
Ahora vamos a analizar la relación de los tipos de pasajeros con los
ingresos totales. De nuevo usaremos el coeficiente de correlación tanto
para los pasajeros nacionales como internacionales.
cor(DF$IT, DF$NPN, use="complete.obs")
cor(DF$IT, DF$NPI, use="complete.obs")
De los coeficientes dados se encuentra que:
- Ambos demuestran que tanto los pasajeros nacionales como
internacionales poseen una buena y ascendente relación lineal con los
ingresos totales.
- Ambos son menores al cor de los pasajeros totales
con los ingresos totales. Indica que si se usa solo a los pasajeros
nacionales o solo a los internacionales para aproximar los ingresos
totales, se tendrá una precisión menor a que si se usará la suma de
ambos.
- El cor de los pasajeros internacionales es
ligeramente superior al de los pasajeros nacionales, mostrando que su
relación lineal con los ingresos totales es ligeramente más acorde que
la relación lineal de los pasajeros nacionales.
Ahora construyamos los modelos de regresión lineal para cada uno.
modelo = lm(DF$IT ~ DF$NPN, data=DF)
modelo
d <- data.frame("X"=DF$NPN/1000, "Y"=DF$IT/1000000)
modelo = lm(d$Y ~ d$X, data=d)
modelo
modelo = lm(DF$IT ~ DF$NPI, data=DF)
modelo
d <- data.frame("X"=DF$NPI/1000, "Y"=DF$IT/1000000)
modelo = lm(d$Y ~ d$X, data=d)
modelo
rm(d)
Vemos que los modelos difieren en una cantidad considerable en cuanto
a su pendiente, sin embargo, su intercepto es bastante similar, vamos a
graficar estos modelos.
par(mfrow=c(1,2))
plot(DF$NPN/1000, DF$IT/1000000, xlab = "Numero de pasajeros nacionales (miles)", ylab = "Ingresos totales (millones de US$)", col="red", pch="•")
abline(a= -0.36033, b=0.02451, col="#f72585")
plot(DF$NPI/1000, DF$IT/1000000, xlab = "Numero de pasajeros internacionales (miles)", ylab = "Ingresos totales (millones de US$)", col="blue", pch="•")
abline(a= 0.31996, b=0.04772, col="#0077b6")
Objetivo 3
Para averiguar cual es el aeropuerto que mayor tráfico y el
aeropuerto que mayores ingresos genera en el Perú en los años (2020,
2021 y 2022), analizaremos la distribución de Ingresos Totales
planteando gráficos y relaciones.
Analizando la distribución de Ingresos Totales
plot_ly(x = ~DF$IT/1000000,
type="histogram",
color = ~DF$Infraestructura,
nbinsx = 40
)%>%
layout(yaxis = list( title = "Frecuencia" ),
xaxis = list( title = "Ingresos totales (Millones de US$)",
nticks = 20))
Gracias al histograma se dice que los datos de los ingresos totales
son totalmente asimétricos y se encuentran acumulados en un intervalo de
0 - 0.8 millones de dolares. Es decir la mayoría de aeropuertos
determinados en cierto mes y cierto año posee unos ingresos totales de
entre 0 y 0.8 millones de dolares. Esto puede ocurrir debido a datos
atípicos, construyamos un Boxplot para que nos ayude.
plot_ly(DF, x=~DF$IT/1000000,
type = "box")%>%
layout(
xaxis = list( title = "Ingresos totales (Millones de US$)"))
Usando un Boxplot simple se comprueba como los datos de los ingresos
totales están demasiado dispersos gracias a cierta cantidad de datos
atípicos. Ahora es necesario averiguar de donde provienen estos datos
atípicos y que nos quieren decir. Para ello crearemos diferentes
Boxplots basados en meses, infraestructuras y aeropuertos.
plot_ly(DF, x = ~IT/1000000,
y = ~Mes,
color= ~Mes,
type="box") %>%
layout(yaxis = list( title = "Mes"),
xaxis = list( title = "Ingresos totales (Millones de US$)"))
Warning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Con este gráfico podemos descartar que los datos atípicos provengan
de un o varios meses en específico.
plot_ly(DF, x = ~IT/1000000,
y = ~Infraestructura,
color= ~Infraestructura,
type="box") %>%
layout(yaxis = list( title = "Infraestructura"),
xaxis = list( title = "Ingresos totales (Millones de US$)"))
En este gráfico se observa como Lima Airport Partners S.R.L rebasa
por mucho a las otras infraestructuras en cuanto a ingresos totales se
refiere. Aquí podemos ya saber que esos datos atípicos de ingresos están
generados en su gran mayoría por la infraestructura Lima Airport
Partners S.R.L. Además es importante mencionar que la infraestructura
COR no aparece en la gráfica pues no ha declarado ningún ingreso
total.
Otros datos a considerar:
El boxplot de Lima Airport Partners S.R.L se ve perfecto cuando
lo aislamos, muestra que no posee ningún dato atípico.
El boxplot de Aeropuertos del Perú S.A al aislarlo se observa
como la caja es bastante pequeña y posee muchos datos atípicos que son
mayores a la mediana.
El boxplot de Aeropuertos Andinos del Perú S.A muestra un bigote
pegado al cuartil 25%, demostrando que los datos del 25% inferior son
iguales o muy cercanos. Asimismo se observan datos atipicos mayores a la
mediana.
plot_ly(DF, x = ~IT/1000000,
y = ~Aeropuerto,
color= ~Aeropuerto,
type="box"
) %>%
layout(yaxis = list( title = "Aeropuertos"),
xaxis = list( title = "Ingresos totales (Millones de US$)"))
Warning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Gracias a los 3 gráficos podemos concluir que:
El aeropuerto de Lima cuya entidad prestadora es la LAP, es la
responsable de los datos atípicos y además es el que más ingresos
totales genera.
El boxplot del aeropuerto Lima aislado en base a los ingresos
totales muestra que existe datos menores a la mediana más sin embargo su
minimo se apróxima por mucho al quartil inferior 25%.
La infraestructura LAP trabaja en Lima y se refiere al Aeropuerto
Internacional Jorge Chávez. Esto nos quiere decir que en el Perú, el
aeropuerto que genera más ingresos es el Jorge Chávez.
Numero de Pasajeros vs Aeropuertos
plot_ly(DF,y = ~NP/1000,
x = ~as.factor(Aeropuerto),
type="bar",
marker = list(color=c("lightblue"))
)%>%
layout(xaxis = list( title = "Aeropuertos"),
yaxis = list( title = "Numero de pasajeros (miles)"))
Con esta gráfico se corrobora que el Aeropuerto de Lima (Aeropuerto
Internacional Jorge Chávez) genera la mayor cantidad de ingresos y
además recibe a la mayor cantidad de pasajeros respecto al resto del
Perú. Otros aeropuertos notables son Cusco, Arequipa e Iquitos donde
Cusco es el que más pasajeros recibe fuera de Lima. Se procede a dibujar
el numero de pasajeros, los ingresos totales y los aeropuertos.
plot_ly(DF,x = ~NP/1000,
y = ~IT/1000000,
type="scatter",
color = ~as.factor(Aeropuerto)
)
El gráfico nos deja en claro la estrecha relación de la cantidad de
pasajeros con la de ingresos que posee el aeropuerto de Lima y como este
sobresale por mucho del resto de aeropuertos. Se concluye que los datos
atípicos provenientes de ingresos totales eran y nos contaban sobre las
peculiaridades del caso Lima.
Ingresos T U U A Total vs Ingresos Totales
Se eligió la comparación de las T U U A, porque esta es la TARIFA
UNIFICADA POR USO DE AEROPUERTO, es decir es una tarifa que como
consumidores debemos de pagar. El objetivo aquí es analizar cuanto de
los ingresos totales provienen directamente de los bolsillos de los
pasajeros.
plot((DF$TUUAN/1000000 + DF$TUUAI/1000000), DF$IT/1000000, xlab = "Ingresos TUUA (millones de US$)", ylab = "Ingresos totales (millones de US$)", col="#926c15", pch="•")
Comenzamos comparando el numero de pasajeros en miles totales, suma
de pasajeros internacionales y nacionales, con los ingresos totales de
cada aeropuerto en determinado mes y año en millones de dolares. A
simple vista se puede ver un cierto tipo de relación lineal, sin embargo
tenemos que comprobarlo. Usaremos el coeficiente de correlación ya que
este no toma en cuenta la escala de las unidades, perfecto para nuestro
estudio.
cor(DF$IT, DF$TUUAI + DF$TUUAN, use="complete.obs")
Tenemos un coeficiente de correlación que esta muy próximo a 1, es
decir esta relación es casi perfectamente lineal y con tendencia
ascendente.
Ahora crearemos un modelo de regresión lineal.
TUUA <- DF$TUUAI+DF$TUUAN
modelo = lm(DF$IT ~ TUUA, data=DF)
modelo
Call:
lm(formula = DF$IT ~ TUUA, data = DF)
Coefficients:
(Intercept) TUUA
155740.38 2.19
d <- data.frame("X"= (DF$TUUAI + DF$TUUAN)/100000, "Y"=DF$IT/1000000)
modelo = lm(d$Y ~ d$X, data=d)
modelo
Call:
lm(formula = d$Y ~ d$X, data = d)
Coefficients:
(Intercept) d$X
0.1557 0.2190
rm(d)
Del modelo creado se obtiene el intercepto, es decir cuando la TUUA
valdrá cero y la pendiente, en este caso es relativamente baja pero
ascendente.
plot((DF$TUUAN+DF$TUUAI)/100000, DF$IT/1000000, xlab = "Ingresos TUUA total (millones de US$)", ylab = "Ingresos totales (millones de US$)", col="#926c15", pch="•")
abline(a= 0.1557, b=0.2190, col="#c9a227")

Detallamos entonces que los ingresos totales guardan una alta
relación con los ingresos generados por las TUUA y dependen en gran
medida de estas, ergo la cantidad de pasajeros.
Objetivo 4
Ahora haremos un análisis de la pandemia y postpandemia de los
ingresos totales en los aeropuertos del Perú en los años (2020,2021 y
2022)
Pandemia vs PostPandemia
DF2020 <- filter(DF, DF$Año=="2020")
DF2021 <- filter(DF, DF$Año=="2021")
DF2022 <- filter(DF, DF$Año=="2022")
DF2020 %>% group_by(Mes,Año) %>% summarise(IT = sum(IT, na.rm=TRUE), NP = sum(NP, na.rm = TRUE)) -> DF2020
DF2021 %>% group_by(Mes,Año) %>% summarise(IT = sum(IT, na.rm=TRUE), NP = sum(NP, na.rm = TRUE)) -> DF2021
DF2022 %>% group_by(Mes,Año) %>% summarise(IT = sum(IT, na.rm=TRUE), NP = sum(NP, na.rm = TRUE)) -> DF2022
plot_ly(y = ~DF2020$IT/1000000,
x = ~DF2020$Mes,
type="bar",
name="2020",
marker = list(color = '#57cc99')
)%>%
add_trace(y = ~DF2021$IT/1000000,
x = ~DF2021$Mes,
type="bar",
name="2021",
marker = list(color = '#38a3a5')
)%>%
add_trace(y = ~DF2022$IT/1000000,
x = ~DF2022$Mes,
type="bar",
name="2022",
marker = list(color = '#22577a')
)%>%
layout(xaxis = list( title = "Meses"),
yaxis = list( title = "Ingresos totales (Millones de US$)",
nticks = 10,
range = list(0,45)),
barmode="group")
Del gráfico de barras podemos observar:
La distribución de los ingresos totales en base a los meses del
año.
Existe una asimetria notable entre los datos en el año 2020. Esta
asimetria se explica por el surgimiento del Covid-19. Los ingresos
bajaron bastante en proporción a la media.
Un patrón de crecimiento sobre los ingresos totales dependiendo
de los meses. En algunos meses los ingresos totales son esperado a ser
mayores que en otros meses, uno de los factores que pueden influir en
esto son las vacaciones pues están estrechamente relacionas con el
número de pasajeros a abordar en un aeropuerto.
plot_ly() %>%
add_trace(y = ~DF2020$IT/1000000,
x = ~DF2020$Mes,
type="scatter",
mode="lines+markers",
name="2020",
marker = list(color = '#57cc99'),
line = list(color = '#57cc99'),
fill = "tonexty",
fillcolor = 'rgba(197,237,211,0.3)'
)%>%
add_trace(DF2021, y = ~DF2021$IT/1000000,
x = ~DF2021$Mes,
type="scatter",
mode="lines+markers",
name="2021",
marker = list(color = '#38a3a5'),
line = list(color = '#38a3a5'),
fill = "tonexty",
fillcolor = 'rgba(106,166,169,0.3)'
)%>%
add_trace(y = ~DF2022$IT/1000000,
x = ~DF2022$Mes,
type="scatter",
mode="lines+markers",
name="2022",
marker = list(color = '#22577a'),
line = list(color = '#22577a'),
fill = "tonexty",
fillcolor = 'rgba(68,102,122,0.3)'
)%>%
layout(xaxis = list( title = "Meses"),
title = "Evolutivo Ingresos",
yaxis = list( title = "Ingresos totales (Millones de US$)",
range = list(0,45))
)
NA
plot_ly() %>%
add_trace(y = ~DF2020$NP/1000,
x = ~DF2020$Mes,
type="scatter",
mode="lines+markers",
name="2020",
marker = list(color = '#E09F3E'),
line = list(color = '#E09F3E'),
fill = "tonexty",
fillcolor = 'rgba(225,183,123,0.3)'
)%>%
add_trace(DF2021, y = ~DF2021$NP/1000,
x = ~DF2021$Mes,
type="scatter",
mode="lines+markers",
name="2021",
marker = list(color = '#9E2A2B'),
line = list(color = '#9E2A2B'),
fill = "tonexty",
fillcolor = 'rgba(158,72,74,0.3)'
)%>%
add_trace(y = ~DF2022$NP/1000,
x = ~DF2022$Mes,
type="scatter",
mode="lines+markers",
name="2022",
marker = list(color = '#540B0E'),
line = list(color = '#540B0E'),
fill = "tonexty",
fillcolor = 'rgba(87,45,47,0.3)'
)%>%
layout(xaxis = list( title = "Meses"),
title = "Evolutivo Pasajeros",
yaxis = list( title = "Numero de Pasajeros (Miles)"))
De los gráficos evolutivos podemos apreciar:
Como es el comportamiento de los ingresos totales frente a los
meses y a los años marcados por la pandemia.
En el mes de Febrero del año 2020 comienza una caída drástica en
los ingresos hasta Abril del mismo año donde comienza a estabilizarse.
Este periodo coincide con la aparición del Covid-19 en Perú y el
establecimiento de las medidas de confinamiento. El confinamiento indica
que el número de pasajeros se reduce en gran proporción. Esta causa
también se puede observar en el evolutivo de pasajeros y el como su
número de cae hasta 0 o casi 0. Los aeropuerto tuvieron consecuencias
que tardaron mucho en disiparse Muestra de ello es como se tardó 2 años
y 5 meses para volver a un punto similar al de Febrero 2020 en ingresos
totales.
```r
round(100 - ((filter(DF2020, Mes == "Abril")$IT/1000000 )/( filter(DF2020, Mes == "Febrero")$IT/1000000) * 100) ,2)
```
```
[1] 86.68
```
```r
round( - filter(DF2020, Mes == "Abril")$IT/1000000 + filter(DF2020,Mes == "Febrero")$IT/1000000, 2)
```
```
[1] 31.67
```
La pérdida del mes de Abril del 2020 respecto al mes de Febrero
del 2020 fue del 86.68% suponiendo una diferencia de 31.76 millones de
dolares.
A partir del mes de Abril se estabilizan los ingresos del año
2020. Estos son bajos pero se observa una tendencia ascendente.
Tendencia que continua en los años 2021 y 2022 a medida que el
confinamiento se levanta, la pandemia se controla y el numero de
pasajeros aumenta.
Conclusión
A razón de resumen, en nuestro análisis sobre los factores
influyentes en los ingresos totales de los aeropuertos se gráfico la
distribución de los ingresos totales, las diferentes relaciones entre
variables tales como la última vista (Ingresos TUUA vs Ingresos
Totales), (cantidad de pasajeros y aeropuertos). Asimismo observamos y
describimos el comportamiento evolutivo de los ingresos totales respecto
a los años vividos en pandemia y pos-pandemia. Finalmente, con la
información recolectada y el estudio realizado se encontró que los
ingresos totales generados por los aeropuertos en el Perú dependen
altamente en los consumidores o pasajeros, siendo la TUUA y el IRAD los
ejemplos más claros de ello.
LS0tDQp0aXRsZTogIkVzdGFkaXN0aWNhcyBzb2JyZSBsb3MgYWVyb3B1ZXJ0b3MiDQphdXRob3I6ICJHcnVwbyA3LCBTZWNjacOzbiA5Ig0KZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJWQgJUIsICVZJylgIg0KZWRpdG9yOiB2aXN1YWwNCmZvcm1hdDogaHRtbA0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiBubw0KICAgICAgc21vb3RoX3Njcm9sbDogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiBubw0KICAgIHRvY19kZXB0aDogMg0KDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCiAgICBkZl9wcmludDogcGFnZWQNCi0tLQ0KDQojICoqQWx1bW5vcyBkZWwgZ3J1cG86KioNCg0KfCBBbHVtbm8gICAgICAgICAgICAgICAgICAgICAgICAgIHwgKipDw7NkaWdvKiogICAgfCAqKkNvcnJlbyoqICAgICAgICAgICAgICAgICAgICAgfCAqKlBvcmNlbnRhamUgZGUgVHJhYmFqbyoqIHwNCnwtLS0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tfA0KfCAqKipTYW1pciBTdGVmYW5vIFN1YXJleiBSaW9zKioqIHwgKioyMDIyMTA2MTEqKiB8ICoqc2FtaXIuc3VhcmV6XEB1dGVjLmVkdS5wZSoqICB8ICoqMTAwJSoqICAgICAgICAgICAgICAgICAgICB8DQp8ICoqTWlsdG9uIEVzdGViYW4gUm9ibGVzIFJleWVzKiogfCAqKjIwMjIxMDQxNioqIHwgKiptaWx0b24ucm9ibGVzXEB1dGVjLmVkdS5wZSoqIHwgKioxNSUqKiAgICAgICAgICAgICAgICAgICAgfA0KfCAqKkdhYnJpZWwgRm91cm5pZXIqKiAgICAgICAgICAgfCAqKjIwMTYxMDAwMioqIHwgKioqKiB8ICoqeCUqKiAgICAgICAgICAgICAgICAgICAgfA0KfCAqKkthcmVuKiogICB8ICoqMjAxNjEwMDAyKiogfCAqKioqIHwgKip4JSoqICAgICAgICAgICAgICAgICAgICB8DQoNCg0KIyAqKkludHJvZHVjY2nDs24qKg0KDQojIyBUZW1hDQoNCkFuw6FsaXNpcyBtZW5zdWFsIGRlIGxhIHJlbGFjacOzbiBlbnRyZSBuw7ptZXJvIGRlIHBhc2FqZXJvcyBlIGluZ3Jlc29zIHRvdGFsZXMgcG9yIGFlcm9wdWVydG8gZGVsIFBlcsO6ICgyMDIwLTIwMjIpLg0KDQojIyBSZWxldmFuY2lhDQoNCkxhIHJlbGV2YW5jaWEgZGUgbnVlc3RybyBwcm95ZWN0byBzZSBjZW50cmEgZW4gdmFyaW9zIGFzcGVjdG9zLCBlbCBtYXMgYsOhc2ljbyBkZSBlbGxvcyBlcyBlbCB0cmFuc3BvcnRlIGHDqXJlbywgcXVlIGR1cmFudGUgbXVjaG8gdGllbXBvIGRlIGV2b2x1Y2nDs24sIGhhIHNpZ25pZmljYWRvIHVuYSBvcG9ydHVuaWRhZCBkZSBjb25leGnDs24gZ2xvYmFsLCBqdW50byBhIGVsbG8sIGRlc2Fycm9sbG8gZWNvbsOzbWljbyB5IHNvY2lhbC4gTGEgZGVsaW1pdGFjacOzbiB0ZW1wb3JhbCBub3MgcGVybWl0ZSBhbmFsaXphciBlbCBpbXBhY3RvIGNydWNpYWwgZGUgbGEgcGFuZGVtaWEgZGUgQ09WSUQtMTksIGRlc2VuY2FkZW5hZGEgZW4gMjAyMC4gQWwgZXhhbWluYXIgbGEgcmVsYWNpw7NuIGVudHJlIGVsIG7Dum1lcm8gZGUgcGFzYWplcm9zIHkgbG9zIGluZ3Jlc29zIGVuIGRpdmVyc29zIHJ1YnJvcywgbnVlc3RybyBwcm95ZWN0byBvZnJlY2UgdW4gYW7DoWxpc2lzIGludGVncmFsIGRlIGxhIHNhbHVkIGZpbmFuY2llcmEgeSByZW50YWJpbGlkYWQgZGUgY2FkYSBhZXJvcHVlcnRvIGVzdHVkaWFkby4gQWRlbcOhcywgYWwgY29uc2lkZXJhciBsYSBpbmZsdWVuY2lhIGRlIGxhIHBhbmRlbWlhLCBleHBsb3JhcmVtb3MgcG9zaWJsZXMgZGVjbGl2ZXMgbyByZWFjdGl2YWNpb25lcyBkdXJhbnRlIGVsIHBlcmlvZG8gMjAyMC0yMDIyLiBFc3RvIGFkcXVpZXJlIGdyYW4gaW1wb3J0YW5jaWEgZW4gZWwgY29udGV4dG8gZWNvbsOzbWljbyBkZWwgUGVyw7osIHlhIHF1ZSBlbCB0dXJpc21vIGVzIHVuIHNlY3RvciBxdWUgYWRlbcOhcyBkZSBlc3RhciBtdXkgbGlnYWRvIGFsIHRyYW5zcG9ydGUgYcOpcmVvLCBhcG9ydGEgc2lnbmlmaWNhdGl2YW1lbnRlIGEgbGEgZWNvbm9tw61hIG5hY2lvbmFsLiBOdWVzdHJvIHByb3llY3RvIHByb3BvcmNpb25hcsOhIGluZm9ybWFjacOzbiB2YWxpb3NhIHBhcmEgbGEgdG9tYSBkZSBkZWNpc2lvbmVzIGVuIGVzdGUgw6FtYml0by4NCg0KDQojICoqT2JqZXRpdm8qKg0KDQpFdmFsdWFyIGxvcyBmYWN0b3JlcyBxdWUgaW5mbHV5ZW4gZW4gbG9zIGluZ3Jlc29zIHRvdGFsZXMgKFVTJCkgcG9yIG1lcyB5IGHDsW8gZW4gY2FkYSBhZXJvcHVlcnRvIGVuIGVsIFBlcsO6Lg0KDQojIyBPYmpldGl2byBTZWN1bmRhcmlvcw0KDQotICAgQ29tcGFyYXIgbG9zIGluZ3Jlc29zIHRvdGFsZXMgY29uIGxvcyBydWJyb3MgZW4gbG9zIGFlcm9wdWVydG9zIGRlbCBQZXLDug0KDQotICAgQ29tcGFyYXIgbG9zIGluZ3Jlc29zIHRvdGFsZXMgY29uIGVsIG7Dum1lcm8gZGUgcGFzYWplcm9zIGVuIGxvcyBhZXJvcHVlcnRvcyBkZWwgUGVyw7ogZXZhbHVhbmRvIHN1IGluZmx1ZW5jaWENCg0KLSAgIERldGVybWluYXIgZWwgYWVyb3B1ZXJ0byBjb24gbWF5b3IgYWZsdWVuY2lhIGRlIHBhc2FqZXJvcyB5IGVsIGRlIG1heW9yIGluZ3Jlc29zIGRlbCBQZXLDug0KDQotICAgQ29tcGFyYXIgbG9zIGluZ3Jlc29zIHRvdGFsZXMgKFVTJCkgZHVyYW50ZSBsYSBwYW5kZW1pYSB5IHBvc3QgcGFuZGVtaWEgZW4gZWwgUGVyw7oNCg0KIyMgVGFibGEgZGUgdmFyaWFibGVzDQoNCiMgTGlicmVyw61hcw0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0Kcm0obGlzdD1scygpKQ0KbGlicmFyeShwbHlyKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KHRpZHlyKQ0KDQpgYGANCg0KIyBCYXNlIGRlIGRhdG9zDQoNCmBgYHtyIGVjaG89RkFMU0V9DQpJVFMgPC0gcmVhZF9jc3YoIlJlY2F1ZGFjaW9uSW5ncmVzb3NUb3RhbGVzLmNzdiIpDQpJUlM8LSByZWFkX2NzdigiUmVjYXVkYWNpb25JbmdyZXNvc1JlZ3VsYWRvcy5jc3YiKQ0KVFAgPC0gcmVhZF9jc3YoIlRyYWZpY29QYXNhamVyb3MuY3N2IikNCmBgYA0KIyAqKkRhdG9zKioNCg0KIyMgVGFibGEgZGUgdmFyaWFibGVzDQoNCkHDsW86IFZhcmlhYmxlIGNhdGVnw7NyaWNhIHF1ZSBpbmRpY2EgZWwgYcOxbyBkZSBsYSByZWNvbGVjY2nDs24gZGUgaW5mb3JtYWNpw7NuLg0KDQpNZXM6IFZhcmlhYmxlIGNhdGVnw7NyaWNhIHF1ZSBpbmRpY2EgZWwgbWVzIGRlIGxhIHJlY29sZWNjacOzbiBkZSBpbmZvcm1hY2nDs24uDQoNCkFlcm9wdWVydG86IFZhcmlhYmxlIGN1YWxpdGF0aXZhIHF1ZSBpbmRpY2EgZWwgYWVyb3B1ZXJ0byBkZWwgY3VhbCBzZSByZWNvbGVjdGEgbGEgaW5mb3JtYWNpw7NuDQoNCkluZnJhZXN0cnVjdHVyYTogVmFyaWFibGUgY3VhbGl0YXRpdmEgcXVlIGluZGljYSBhIHF1ZSBlbnRpZGFkIHBlcnRlbmVjZSBsYSBpbmZyYWVzdHJ1Y3R1cmEgZGVsIGFlcm9wdWVydG8gZGVsIGN1YWwgc2UgcmVjb2xlY3RhIGxhIGluZm9ybWFjacOzbi4NCg0KSVQ6IFZhcmlhYmxlIGN1YW50aXRhdGl2YSBxdWUgcmVwcmVzZW50YSBsb3MgaW5ncmVzb3MgdG90YWxlcyBlbiBkb2xhcmVzIHF1ZSBoYSByZWdpc3RyYWRvIGVsIGFlcm9wdWVydG8NCg0KSVI6IFZhcmlhYmxlIGN1YW50aXRhdGl2YSBxdWUgcmVwcmVzZW50YSBsb3MgaW5ncmVzb3MgcmVndWxhZG9zIGVuIGRvbGFyZXMgcXVlIGhhIHJlZ2lzdHJhZG8gZWwgYWVyb3B1ZXJ0bw0KDQpUVVVBTjogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBxdWUgaGEgZ2VuZXJhZG8gbGEgVEFSSUZBIFVOSUZJQ0FEQSBQT1IgVVNPIERFIEFFUk9QVUVSVE8gZGUgdGlwbyBuYWNpb25hbC4NCg0KVFVVQU46IFZhcmlhYmxlIGN1YW50aXRhdGl2YSBxdWUgcmVwcmVzZW50YSBlbCBpbmdyZXNvIGVuIGRvbGFyZXMgcXVlIGhhIGdlbmVyYWRvIGxhIFRBUklGQSBVTklGSUNBREEgUE9SIFVTTyBERSBBRVJPUFVFUlRPIGRlIHRpcG8gaW50ZXJuYWNpb25hbC4NCg0KTlBJOiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgZWwgbnVtZXJvIGRlIHBhc2FqZXJvcyBpbnRlcm5hY2lvbmFsZXMgcXVlIGhhIHJlZ2lzdHJhZG8gZWwgYWVyb3B1ZXJ0bw0KDQpOUE46IFZhcmlhYmxlIGN1YW50aXRhdGl2YSBxdWUgcmVwcmVzZW50YSBlbCBudW1lcm8gZGUgcGFzYWplcm9zIG5hY2lvbmFsZXMgcXVlIGhhIHJlZ2lzdHJhZG8gZWwgYWVyb3B1ZXJ0bw0KDQpJUkFEX1ZFUjogVmFyaWFibGUgY2F0ZWfDs3JpY2EgcXVlIHJlcHJlc2VudGEgc2kgZWwgYWVyb3B1ZXJ0byBvYnRpZW5lIGluZ3Jlc29zIHBvciBhdGVycml6YWplIHkgZGVzcGVndWUuDQoNCklSQUQ6IFZhcmlhYmxlIGN1YW50aXRhdGl2YSBxdWUgcmVwcmVzZW50YSBlbCBpbmdyZXNvIGVuIGRvbGFyZXMgZGVsIGFlcm9wdWVydG8gcG9yIGF0ZXJyaXphamUgeSBkZXNwZWd1ZS4NCg0KQUFETV9WRVI6IFZhcmlhYmxlIGNhdGVnw7NyaWNhIHF1ZSByZXByZXNlbnRhIHNpIGVsIGFlcm9wdWVydG8gb2J0aWVuZSBpbmdyZXNvcyBwb3IgZWwgYWxxdWlsZXIgZGUgw6FyZWFzIGRlIG1hbnRlbmltaWVudG8uDQoNCkFBRE06IFZhcmlhYmxlIGN1YW50aXRhdGl2YSBxdWUgcmVwcmVzZW50YSBlbCBpbmdyZXNvIGVuIGRvbGFyZXMgcG9yIGVsIGFscXVpbGVyIGRlIMOhcmVhcyBkZSBtYW50ZW5pbWllbnRvLg0KDQpBREVQX1ZFUjogVmFyaWFibGUgY2F0ZWfDs3JpY2EgcXVlIHJlcHJlc2VudGEgc2kgZWwgYWVyb3B1ZXJ0byBvYnRpZW5lIGluZ3Jlc29zIHBvciBlbCBhbHF1aWxlciBkZSBlc3BhY2lvcyBkZSBwdWJsaWNpZGFkLg0KDQpBREVQOiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgZWwgaW5ncmVzbyBlbiBkb2xhcmVzIHBvciBlbCBhbHF1aWxlciBkZSBlc3BhY2lvcyBkZSBwdWJsaWNpZGFkLg0KDQpBTENfVkVSOiBWYXJpYWJsZSBjYXRlZ8OzcmljYSBxdWUgcmVwcmVzZW50YSBzaSBlbCBhZXJvcHVlcnRvIG9idGllbmUgaW5ncmVzb3MgcG9yIGVsIGFscXVpbGVyIGRlIGxvY2FsZXMgY29tZXJjaWFsZXMuDQoNCkFMQzogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBwb3IgZWwgYWxxdWlsZXIgZGUgbG9jYWxlcyBjb21lcmNpYWxlcy4NCg0KQU9PQV9WRVI6IFZhcmlhYmxlIGNhdGVnw7NyaWNhIHF1ZSByZXByZXNlbnRhIHNpIGVsIGFlcm9wdWVydG8gb2J0aWVuZSBpbmdyZXNvcyBwb3IgZWwgYWxxdWlsZXIgZGUgb2ZpY2luYXMgZGUgb3BlcmFjaW9uZXMgZGUgYWVyb2zDrW5lYXMuDQoNCkFPT0E6IFZhcmlhYmxlIGN1YW50aXRhdGl2YSBxdWUgcmVwcmVzZW50YSBlbCBpbmdyZXNvIGVuIGRvbGFyZXMgcG9yIGVsIGFscXVpbGVyIGRlIG9maWNpbmFzIGRlIG9wZXJhY2lvbmVzIGRlIGFlcm9sw61uZWFzLg0KDQpBREFIX1ZFUjogVmFyaWFibGUgY2F0ZWfDs3JpY2EgcXVlIHJlcHJlc2VudGEgc2kgZWwgYWVyb3B1ZXJ0byBvYnRpZW5lIGluZ3Jlc29zIHBvciBlbCBhbHF1aWxlciBkZSBhbG1hY2VuZXMvaGFuZ2FyZXMuDQoNCkFEQUg6IFZhcmlhYmxlIGN1YW50aXRhdGl2YSBxdWUgcmVwcmVzZW50YSBlbCBpbmdyZXNvIGVuIGRvbGFyZXMgcG9yIGVsIGFscXVpbGVyIGRlIGFsbWFjZW5lcy9oYW5nYXJlcy4NCg0KQUVIRV9WRVI6IFZhcmlhYmxlIGNhdGVnw7NyaWNhIHF1ZSByZXByZXNlbnRhIHNpIGVsIGFlcm9wdWVydG8gb2J0aWVuZSBpbmdyZXNvcyBwb3IgbGEgYXRlbmNpw7NuIGVuIGhvcmFzIGV4dHJhcy4NCg0KQUVIRTogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBwb3IgbGEgYXRlbmNpw7NuIGVuIGhvcmFzIGV4dHJhcy4NCg0KSVJFQV9WRVI6IFZhcmlhYmxlIGNhdGVnw7NyaWNhIHF1ZSByZXByZXNlbnRhIHNpIGVsIGFlcm9wdWVydG8gb2J0aWVuZSBpbmdyZXNvcyBwb3IgZWwgZXN0YWNpb25hbWllbnRvIGRlIGFlcm9uYXZlcy4NCg0KSVJFQTogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBwb3IgZWwgZXN0YWNpb25hbWllbnRvIGRlIGFlcm9uYXZlcy4NCg0KSVJJRl9WRVI6IFZhcmlhYmxlIGNhdGVnw7NyaWNhIHF1ZSByZXByZXNlbnRhIHNpIGVsIGFlcm9wdWVydG8gb2J0aWVuZSBpbmdyZXNvcyBwb3IgcmVlbWJvbHNvIGVuIGluZ3Jlc29zIGZpbmFuY2llcm9zLg0KDQpJUklGOiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgZWwgaW5ncmVzbyBlbiBkb2xhcmVzIHBvciByZWVtYm9sc28gZW4gaW5ncmVzb3MgZmluYW5jaWVyb3MuDQoNCklSUl9WRVI6IFZhcmlhYmxlIGNhdGVnw7NyaWNhIHF1ZSByZXByZXNlbnRhIHNpIGVsIGFlcm9wdWVydG8gb2J0aWVuZSBpbmdyZXNvcyBwb3IgcmVlbWJvbHNvcy4NCg0KSVJSOiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgZWwgaW5ncmVzbyBlbiBkb2xhcmVzIHBvciByZWVtYm9sc29zLg0KDQpOUDogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIG51bWVybyBkZSBwYXNhamVyb3MgdG90YWxlcyBxdWUgaGEgcmVnaXN0cmFkbyBlbCBhZXJvcHVlcnRvLg0KDQoNCiMgQ3JlYWNpw7NuIGRlbCBEYXRhZnJhbWUNCg0KQ3JlYW5kbyBlbCBEYXRhRnJhbWUgYSBwYXJ0aXIgZGUgbGEgdmFyaWFibGUgSW5ncmVzb3MgVG90YWxlcyAoSVQpDQoNCmBgYHtyfQ0KSVRTIDwtIGZpbHRlcihJVFMsIEHDsW8gJWluJSBjKCIyMDIwIiwiMjAyMSIsIjIwMjIiKSkNCklUUyAlPiUgZ3JvdXBfYnkoQcOxbyxNZXMsQWVyb3B1ZXJ0byxJbmZyYWVzdHJ1Y3R1cmEpICU+JSBzdW1tYXJpc2UoSVQgPSBzdW0oYEltcG9ydGUgcG9yIFNlcnZpY2lvc2ApKSAtPiBERg0KYGBgDQoNCkltcG9ydGFudGU6IFNlIHRvbWEgZW4gY3VlbnRhIHF1ZSBhbCB1biBhZXJvcHVlcnRvIG5vIGRlY2xhcmFyIHVuIGltcG9ydGUgZGUgc2VydmljaW9zIHBvciB1biB0aXBvIGRlIHJ1YnJvIGNvbW8gZWwgKiphbHF1aWxlciBkZSBlc3BhY2lvcyBwdWJsaWNpdGFyaW9zKiosIGxvcyBpbmdyZXNvcyBlbiBlc3RlIHJ1YnJvIHNlcsOhbiAwLiBQYXJhIGVzdG8gY3JlYXJlbW9zIHVuYSB2YXJpYWJsZSBjb25qdW50YSBhbCBydWJybyBkZSBpbXBvcnRlIHF1ZSB2ZXJpZmljYXLDoSBzaSBlc3RlIGhhIHNpZG8gZGVjbGFyYWRvIG8gbm8sIHNlIGlkZW50aWZpY2Fyw6EgY29uIGVsIG5vbWJyZSBkZSBsYSB2YXJpYWJsZSB5IHVuIHN1ZmlqbyAiXF9WRVIiLiBQZXNlIGEgcXVlIGVzdGEgb3BlcmFjacOzbiBnZW5lcmEgc2VzZ28sIGFsIHRlbmVyIHVuIHNlbnRpZG8gY29uIGxhIHJlYWxpZGFkIHNlIGNvbnNpZGVyYSBxdWUgbm8gZXMgc2lnbmlmaWNhdGl2by4NCg0KVW5pZW5kbyBsYSB2YXJpYWJsZSBOdW1lcm8gZGUgUGFzYWplcm9zIEludGVybmFjaW9uYWxlcyAoTlBJKQ0KDQpgYGB7cn0NClBJIDwtIGZpbHRlcihUUCwgYFRpcG8gZGUgUGFzYWplcm9gID09ICJJTlRFUk5BQ0lPTkFMIikNClBJIDwtIGZpbHRlcihQSSxBw7FvICVpbiUgYygyMDIwLDIwMjEsMjAyMikpDQpQSSA8LSBzZWxlY3QoUEksIC1QZXJpb2RvKQ0KUEkgPC0gc2VsZWN0KFBJLCAtYFRpcG8gZGUgUGFzYWplcm9gKQ0KYGBgDQoNCmBgYHtyfQ0KREYgPC0gbWVyZ2UoREYsUEksIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsID0gVFJVRSkNCkRGIDwtIHJlbmFtZShERiwgIk5QSSIgPSAiTnJvIFBhc2FqZXJvcyIpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFfQ0KREYkTlBJW2lzLm5hKERGJE5QSSldIDwtIDANCg0KI1JlZW1wbGF6byBkZSBOL0EncyBwb3IgMA0KYGBgDQoNClVuaWVuZG8gbGEgdmFyaWFibGUgTnVtZXJvIGRlIFBhc2FqZXJvcyBOYWNpb25hbGVzIChOUE4pDQoNCmBgYHtyfQ0KUE4gPC0gZmlsdGVyKFRQLCBgVGlwbyBkZSBQYXNhamVyb2AgPT0gIk5BQ0lPTkFMIikNClBOIDwtIGZpbHRlcihQTixBw7FvICVpbiUgYygyMDIwLDIwMjEsMjAyMikpDQpQTiA8LSBzZWxlY3QoUE4sIC1QZXJpb2RvKQ0KUE4gPC0gc2VsZWN0KFBOLCAtYFRpcG8gZGUgUGFzYWplcm9gKQ0KYGBgDQoNCmBgYHtyfQ0KREYgPC0gbWVyZ2UoREYsUE4sIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJOUE4iID0gIk5ybyBQYXNhamVyb3MiKQ0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRX0NCkRGJE5QTltpcy5uYShERiROUE4pXSA8LSAwDQoNCiNSZWVtcGxhem8gZGUgTi9BJ3MgcG9yIDANCmBgYA0KDQpVbmllbmRvIGxhIHZhcmlhYmxlIEluZ3Jlc28gUnVicm8gVCBVIFUgQSBOQUNJT05BTCAoVFVVQU4pDQoNCmBgYHtyfQ0KVFVVQU4gPC0gZmlsdGVyKElUUywgYFJ1YnJvIEluZ3Jlc29gID09ICJUIFUgVSBBIE5BQ0lPTkFMIikNClRVVUFOIDwtIGZpbHRlcihUVVVBTixBw7FvICVpbiUgYygyMDIwLDIwMjEsMjAyMikpDQpUVVVBTiA8LSBzZWxlY3QoVFVVQU4sIC0nVGlwbyBJbmdyZXNvJykNClRVVUFOIDwtIHNlbGVjdChUVVVBTiwgLSdSdWJybyBJbmdyZXNvJykNClRVVUFOIDwtIHNlbGVjdChUVVVBTiwgLSdQZXJpb2RvJykNCmBgYA0KDQpgYGB7cn0NCiNDcmVhY2nDs24gZGUgdmFyaWFibGUgZGUgdmVyaWZpY2FjacOzbiBwYXJhIHJlZW1wbGF6byBkZSBOL0Encw0KREYgPC0gbWVyZ2UoREYsIFRVVUFOLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiVFVVQU5fVkVSIiA9ICJJbXBvcnRlIHBvciBTZXJ2aWNpb3MiKQ0KYGBgDQoNCmBgYHtyfQ0KREYgPC0gbWVyZ2UoREYsIFRVVUFOLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiVFVVQU4iID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFfQ0KREYkVFVVQU5fVkVSW2lzLm5hKERGJFRVVUFOX1ZFUildIDwtIDANCkRGJFRVVUFOX1ZFUltERiRUVVVBTl9WRVIgIT0gMF0gPC0gIlNpIg0KREYkVFVVQU5fVkVSW0RGJFRVVUFOX1ZFUiA9PSAiMCJdIDwtICJObyINCkRGJFRVVUFOW2lzLm5hKERGJFRVVUFOKV0gPC0gMA0KI1JlZW1wbGF6byBkZSBOL0EncyBwb3IgMA0KYGBgDQoNClVuaWVuZG8gbGEgdmFyaWFibGUgSW5ncmVzbyBSdWJybyBUIFUgVSBBIElOVEVSTkFDSU9OQUwgKFRVVUFJKQ0KDQpgYGB7cn0NClRVVUFJIDwtIGZpbHRlcihJVFMsIGBSdWJybyBJbmdyZXNvYCA9PSAiVCBVIFUgQSBJTlRFUk5BQ0lPTkFMIikNClRVVUFJIDwtIGZpbHRlcihUVVVBSSxBw7FvICVpbiUgYygyMDIwLDIwMjEsMjAyMikpDQpUVVVBSSA8LSBzZWxlY3QoVFVVQUksIC0nVGlwbyBJbmdyZXNvJykNClRVVUFJIDwtIHNlbGVjdChUVVVBSSwgLSdSdWJybyBJbmdyZXNvJykNClRVVUFJIDwtIHNlbGVjdChUVVVBSSwgLSdQZXJpb2RvJykNCmBgYA0KDQpgYGB7cn0NCkRGIDwtIG1lcmdlKERGLCBUVVVBSSwgYnkgPSBjKCJBw7FvIiwiTWVzIiwiQWVyb3B1ZXJ0byIsIkluZnJhZXN0cnVjdHVyYSIpLCBhbGw9VFJVRSkNCkRGIDwtIHJlbmFtZShERiwgIlRVVUFJX1ZFUiIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikjQ3JlYWNpw7NuIGRlIHZhcmlhYmxlIGRlIHZlcmlmaWNhY2nDs24gcGFyYSByZWVtcGxhem8gZGUgTi9BJ3MNCmBgYA0KDQpgYGB7cn0NCkRGIDwtIG1lcmdlKERGLCBUVVVBSSwgYnkgPSBjKCJBw7FvIiwiTWVzIiwiQWVyb3B1ZXJ0byIsIkluZnJhZXN0cnVjdHVyYSIpLCBhbGw9VFJVRSkNCkRGIDwtIHJlbmFtZShERiwgIlRVVUFJIiA9ICJJbXBvcnRlIHBvciBTZXJ2aWNpb3MiKQ0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRX0NCg0KREYkVFVVQUlfVkVSW2lzLm5hKERGJFRVVUFJX1ZFUildIDwtIDANCkRGJFRVVUFJX1ZFUltERiRUVVVBSV9WRVIgIT0gMF0gPC0gIlNpIg0KREYkVFVVQUlfVkVSW0RGJFRVVUFJX1ZFUiA9PSAiMCJdIDwtICJObyINCkRGJFRVVUFJW2lzLm5hKERGJFRVVUFJKV0gPC0gMA0KI1JlZW1wbGF6byBkZSBOL0EncyBwb3IgMA0KYGBgDQoNClVuaWVuZG8gbGEgdmFyaWFibGUgSW5ncmVzbyBSdWJybyBBVEVSUklaQUpFIFkgREVTUEVHVUUgKElSQUQpDQoNCmBgYHtyfQ0KSVJBRCA8LSBmaWx0ZXIoSVRTLCBgUnVicm8gSW5ncmVzb2AgPT0gIkFURVJSSVpBSkUgWSBERVNQRUdVRSIpDQpJUkFEIDwtIGZpbHRlcihJUkFELEHDsW8gJWluJSBjKDIwMjAsMjAyMSwyMDIyKSkNCklSQUQgPC0gc2VsZWN0KElSQUQsIC0nVGlwbyBJbmdyZXNvJykNCklSQUQgPC0gc2VsZWN0KElSQUQsIC0nUnVicm8gSW5ncmVzbycpDQpJUkFEIDwtIHNlbGVjdChJUkFELCAtJ1BlcmlvZG8nKQ0KYGBgDQoNCmBgYHtyfQ0KDQpERiA8LSBtZXJnZShERiwgSVJBRCwgYnkgPSBjKCJBw7FvIiwiTWVzIiwiQWVyb3B1ZXJ0byIsIkluZnJhZXN0cnVjdHVyYSIpLCBhbGw9VFJVRSkNCkRGIDwtIHJlbmFtZShERiwgIklSQURfVkVSIiA9ICJJbXBvcnRlIHBvciBTZXJ2aWNpb3MiKQ0KI0NyZWFjacOzbiBkZSB2YXJpYWJsZSBkZSB2ZXJpZmljYWNpw7NuIHBhcmEgcmVlbXBsYXpvIGRlIE4vQSdzDQpgYGANCg0KYGBge3J9DQpERiA8LSBtZXJnZShERiwgSVJBRCwgYnkgPSBjKCJBw7FvIiwiTWVzIiwiQWVyb3B1ZXJ0byIsIkluZnJhZXN0cnVjdHVyYSIpLCBhbGw9VFJVRSkNCkRGIDwtIHJlbmFtZShERiwgIklSQUQiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFfQ0KDQpERiRJUkFEX1ZFUltpcy5uYShERiRJUkFEX1ZFUildIDwtIDANCkRGJElSQURfVkVSW0RGJElSQURfVkVSICE9IDBdIDwtICJTaSINCkRGJElSQURfVkVSW0RGJElSQURfVkVSID09ICIwIl0gPC0gIk5vIg0KREYkSVJBRFtpcy5uYShERiRJUkFEKV0gPC0gMA0KI1JlZW1wbGF6byBkZSBOL0EncyBwb3IgMA0KYGBgDQoNClVuaWVuZG8gbGEgdmFyaWFibGUgSW5ncmVzbyBSdWJybyBBTFFVSUxFUiBBUkVBUyBERSBNQU5URU5JTUlFTlRPIChBQURNKQ0KDQpgYGB7cn0NCkFBRE0gPC0gZmlsdGVyKElUUywgYFJ1YnJvIEluZ3Jlc29gID09ICJBTFFVSUxFUiBBUkVBUyBERSBNQU5URU5JTUlFTlRPIikNCkFBRE0gPC0gZmlsdGVyKEFBRE0sQcOxbyAlaW4lIGMoMjAyMCwyMDIxLDIwMjIpKQ0KQUFETSA8LSBzZWxlY3QoQUFETSwgLSdUaXBvIEluZ3Jlc28nKQ0KQUFETSA8LSBzZWxlY3QoQUFETSwgLSdSdWJybyBJbmdyZXNvJykNCkFBRE0gPC0gc2VsZWN0KEFBRE0sIC0nUGVyaW9kbycpDQpgYGANCg0KYGBge3J9DQoNCkRGIDwtIG1lcmdlKERGLCBBQURNLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiQUFETV9WRVIiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQojQ3JlYWNpw7NuIGRlIHZhcmlhYmxlIGRlIHZlcmlmaWNhY2nDs24gcGFyYSByZWVtcGxhem8gZGUgTi9BJ3MNCmBgYA0KDQpgYGB7cn0NCkRGIDwtIG1lcmdlKERGLCBBQURNLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiQUFETSIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUV9DQoNCkRGJEFBRE1fVkVSW2lzLm5hKERGJEFBRE1fVkVSKV0gPC0gMA0KREYkQUFETV9WRVJbREYkQUFETV9WRVIgIT0gMF0gPC0gIlNpIg0KREYkQUFETV9WRVJbREYkQUFETV9WRVIgPT0gIjAiXSA8LSAiTm8iDQpERiRBQURNW2lzLm5hKERGJEFBRE0pXSA8LSAwDQojUmVlbXBsYXpvIGRlIE4vQSdzIHBvciAwDQpgYGANCg0KVW5pZW5kbyBsYSB2YXJpYWJsZSBJbmdyZXNvIEFMUVVJTEVSIERFIEVTUEFDSU9TIFBVQkxJQ0lUQVJJT1MgKEFERVApDQoNCmBgYHtyfQ0KQURFUCA8LSBmaWx0ZXIoSVRTLCBgUnVicm8gSW5ncmVzb2AgPT0gIkFMUVVJTEVSIERFIEVTUEFDSU9TIFBVQkxJQ0lUQVJJT1MiKQ0KQURFUCA8LSBmaWx0ZXIoQURFUCxBw7FvICVpbiUgYygyMDIwLDIwMjEsMjAyMikpDQpBREVQIDwtIHNlbGVjdChBREVQLCAtJ1RpcG8gSW5ncmVzbycpDQpBREVQIDwtIHNlbGVjdChBREVQLCAtJ1J1YnJvIEluZ3Jlc28nKQ0KQURFUCA8LSBzZWxlY3QoQURFUCwgLSdQZXJpb2RvJykNCmBgYA0KDQpgYGB7cn0NCg0KREYgPC0gbWVyZ2UoREYsIEFERVAsIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJBREVQX1ZFUiIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCiNDcmVhY2nDs24gZGUgdmFyaWFibGUgZGUgdmVyaWZpY2FjacOzbiBwYXJhIHJlZW1wbGF6byBkZSBOL0Encw0KYGBgDQoNCmBgYHtyfQ0KREYgPC0gbWVyZ2UoREYsIEFERVAsIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJBREVQIiA9ICJJbXBvcnRlIHBvciBTZXJ2aWNpb3MiKQ0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRX0NCg0KREYkQURFUF9WRVJbaXMubmEoREYkQURFUF9WRVIpXSA8LSAwDQpERiRBREVQX1ZFUltERiRBREVQX1ZFUiAhPSAwXSA8LSAiU2kiDQpERiRBREVQX1ZFUltERiRBREVQX1ZFUiA9PSAiMCJdIDwtICJObyINCkRGJEFERVBbaXMubmEoREYkQURFUCldIDwtIDANCiNSZWVtcGxhem8gZGUgTi9BJ3MgcG9yIDANCmBgYA0KDQpVbmllbmRvIGxhIHZhcmlhYmxlIEluZ3Jlc28gQUxRVUlMRVIgTE9DQUxFUyBDT01FUkNJQUxFUyAoQUxDKQ0KDQpgYGB7cn0NCkFMQyA8LSBmaWx0ZXIoSVRTLCBgUnVicm8gSW5ncmVzb2AgPT0gIkFMUVVJTEVSIExPQ0FMRVMgQ09NRVJDSUFMRVMiKQ0KQUxDIDwtIGZpbHRlcihBTEMsQcOxbyAlaW4lIGMoMjAyMCwyMDIxLDIwMjIpKQ0KQUxDIDwtIHNlbGVjdChBTEMsIC0nVGlwbyBJbmdyZXNvJykNCkFMQyA8LSBzZWxlY3QoQUxDLCAtJ1J1YnJvIEluZ3Jlc28nKQ0KQUxDIDwtIHNlbGVjdChBTEMsIC0nUGVyaW9kbycpDQpgYGANCg0KYGBge3J9DQoNCkRGIDwtIG1lcmdlKERGLCBBTEMsIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJBTENfVkVSIiA9ICJJbXBvcnRlIHBvciBTZXJ2aWNpb3MiKQ0KI0NyZWFjacOzbiBkZSB2YXJpYWJsZSBkZSB2ZXJpZmljYWNpw7NuIHBhcmEgcmVlbXBsYXpvIGRlIE4vQSdzIA0KYGBgDQoNCmBgYHtyfQ0KREYgPC0gbWVyZ2UoREYsIEFMQywgYnkgPSBjKCJBw7FvIiwiTWVzIiwiQWVyb3B1ZXJ0byIsIkluZnJhZXN0cnVjdHVyYSIpLCBhbGw9VFJVRSkNCkRGIDwtIHJlbmFtZShERiwgIkFMQyIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUV9DQoNCkRGJEFMQ19WRVJbaXMubmEoREYkQUxDX1ZFUildIDwtIDANCkRGJEFMQ19WRVJbREYkQUxDX1ZFUiAhPSAwXSA8LSAiU2kiDQpERiRBTENfVkVSW0RGJEFMQ19WRVIgPT0gIjAiXSA8LSAiTm8iDQpERiRBTENbaXMubmEoREYkQUxDKV0gPC0gMA0KI1JlZW1wbGF6byBkZSBOL0EncyBwb3IgMA0KYGBgDQoNClVuaWVuZG8gbGEgdmFyaWFibGUgSW5ncmVzbyBSdWJybyBBTFFVSUxFUiBPRklDSU5BUyBPUEVSQUNJT05FUyBBRVJPTMONTkVBUyAoQU9PQSkNCg0KYGBge3J9DQpBT09BIDwtIGZpbHRlcihJVFMsIGBSdWJybyBJbmdyZXNvYCA9PSAiQUxRVUlMRVIgT0ZJQ0lOQVMgT1BFUkFDSU9ORVMgQUVST0zDjU5FQVMiKQ0KQU9PQSA8LSBmaWx0ZXIoQU9PQSxBw7FvICVpbiUgYygyMDIwLDIwMjEsMjAyMikpDQpBT09BIDwtIHNlbGVjdChBT09BLCAtJ1RpcG8gSW5ncmVzbycpDQpBT09BIDwtIHNlbGVjdChBT09BLCAtJ1J1YnJvIEluZ3Jlc28nKQ0KQU9PQSA8LSBzZWxlY3QoQU9PQSwgLSdQZXJpb2RvJykNCmBgYA0KDQpgYGB7cn0NCg0KREYgPC0gbWVyZ2UoREYsIEFPT0EsIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJBT09BX1ZFUiIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCiNDcmVhY2nDs24gZGUgdmFyaWFibGUgZGUgdmVyaWZpY2FjacOzbiBwYXJhIHJlZW1wbGF6byBkZSBOL0EncyANCmBgYA0KDQpgYGB7cn0NCkRGIDwtIG1lcmdlKERGLCBBT09BLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiQU9PQSIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUV9DQpERiRBT09BX1ZFUltpcy5uYShERiRBT09BX1ZFUildIDwtIDANCkRGJEFPT0FfVkVSW0RGJEFPT0FfVkVSICE9IDBdIDwtICJTaSINCkRGJEFPT0FfVkVSW0RGJEFPT0FfVkVSID09ICIwIl0gPC0gIk5vIg0KREYkQU9PQVtpcy5uYShERiRBT09BKV0gPC0gMA0KYGBgDQoNClVuaWVuZG8gbGEgdmFyaWFibGUgSW5ncmVzbyBSdWJybyBBTFFVSUxFUkVTIERFIEFMTUFDRU4vSEFOR0FSIChBREFIKQ0KDQpgYGB7cn0NCkFEQUggPC0gZmlsdGVyKElUUywgYFJ1YnJvIEluZ3Jlc29gID09ICJBTFFVSUxFUkVTIERFIEFMTUFDRU4vSEFOR0FSIikNCkFEQUggPC0gZmlsdGVyKEFEQUgsQcOxbyAlaW4lIGMoMjAyMCwyMDIxLDIwMjIpKQ0KQURBSCA8LSBzZWxlY3QoQURBSCwgLSdUaXBvIEluZ3Jlc28nKQ0KQURBSCA8LSBzZWxlY3QoQURBSCwgLSdSdWJybyBJbmdyZXNvJykNCkFEQUggPC0gc2VsZWN0KEFEQUgsIC0nUGVyaW9kbycpDQpgYGANCg0KYGBge3J9DQoNCkRGIDwtIG1lcmdlKERGLCBBREFILCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiQURBSF9WRVIiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQojQ3JlYWNpw7NuIGRlIHZhcmlhYmxlIGRlIHZlcmlmaWNhY2nDs24gcGFyYSByZWVtcGxhem8gZGUgTi9BJ3MgDQpgYGANCg0KYGBge3J9DQpERiA8LSBtZXJnZShERiwgQURBSCwgYnkgPSBjKCJBw7FvIiwiTWVzIiwiQWVyb3B1ZXJ0byIsIkluZnJhZXN0cnVjdHVyYSIpLCBhbGw9VFJVRSkNCkRGIDwtIHJlbmFtZShERiwgIkFEQUgiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFfQ0KREYkQURBSF9WRVJbaXMubmEoREYkQURBSF9WRVIpXSA8LSAwDQpERiRBREFIX1ZFUltERiRBREFIX1ZFUiAhPSAwXSA8LSAiU2kiDQpERiRBREFIX1ZFUltERiRBREFIX1ZFUiA9PSAiMCJdIDwtICJObyINCkRGJEFEQUhbaXMubmEoREYkQURBSCldIDwtIDANCmBgYA0KDQpVbmllbmRvIGxhIHZhcmlhYmxlIEluZ3Jlc28gUnVicm8gQVRFTkNJw5NOIEVOIEhPUkFTIEVYVFJBUyAoQUVIRSkNCg0KYGBge3J9DQpBRUhFIDwtIGZpbHRlcihJVFMsIGBSdWJybyBJbmdyZXNvYCA9PSAiQVRFTkNJw5NOIEVOIEhPUkFTIEVYVFJBUyIpDQpBRUhFIDwtIGZpbHRlcihBRUhFLEHDsW8gJWluJSBjKDIwMjAsMjAyMSwyMDIyKSkNCkFFSEUgPC0gc2VsZWN0KEFFSEUsIC0nVGlwbyBJbmdyZXNvJykNCkFFSEUgPC0gc2VsZWN0KEFFSEUsIC0nUnVicm8gSW5ncmVzbycpDQpBRUhFIDwtIHNlbGVjdChBRUhFLCAtJ1BlcmlvZG8nKQ0KYGBgDQoNCmBgYHtyfQ0KDQpERiA8LSBtZXJnZShERiwgQUVIRSwgYnkgPSBjKCJBw7FvIiwiTWVzIiwiQWVyb3B1ZXJ0byIsIkluZnJhZXN0cnVjdHVyYSIpLCBhbGw9VFJVRSkNCkRGIDwtIHJlbmFtZShERiwgIkFFSEVfVkVSIiA9ICJJbXBvcnRlIHBvciBTZXJ2aWNpb3MiKQ0KI0NyZWFjacOzbiBkZSB2YXJpYWJsZSBkZSB2ZXJpZmljYWNpw7NuIHBhcmEgcmVlbXBsYXpvIGRlIE4vQSdzIA0KYGBgDQoNCmBgYHtyfQ0KREYgPC0gbWVyZ2UoREYsIEFFSEUsIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJBRUhFIiA9ICJJbXBvcnRlIHBvciBTZXJ2aWNpb3MiKQ0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRX0NCkRGJEFFSEVfVkVSW2lzLm5hKERGJEFFSEVfVkVSKV0gPC0gMA0KREYkQUVIRV9WRVJbREYkQUVIRV9WRVIgIT0gMF0gPC0gIlNpIg0KREYkQUVIRV9WRVJbREYkQUVIRV9WRVIgPT0gIjAiXSA8LSAiTm8iDQpERiRBRUhFW2lzLm5hKERGJEFFSEUpXSA8LSAwDQpgYGANCg0KVW5pZW5kbyBsYSB2YXJpYWJsZSBJbmdyZXNvIFJ1YnJvIEVTVEFDSU9OQU1JRU5UTyBBRVJPTkFWRVMgKElSRUEpDQoNCmBgYHtyfQ0KSVJFQSA8LSBmaWx0ZXIoSVRTLCBgUnVicm8gSW5ncmVzb2AgPT0gIkVTVEFDSU9OQU1JRU5UTyBBRVJPTkFWRVMiKQ0KSVJFQSA8LSBmaWx0ZXIoSVJFQSxBw7FvICVpbiUgYygyMDIwLDIwMjEsMjAyMikpDQpJUkVBIDwtIHNlbGVjdChJUkVBLCAtJ1RpcG8gSW5ncmVzbycpDQpJUkVBIDwtIHNlbGVjdChJUkVBLCAtJ1J1YnJvIEluZ3Jlc28nKQ0KSVJFQSA8LSBzZWxlY3QoSVJFQSwgLSdQZXJpb2RvJykNCmBgYA0KDQpgYGB7cn0NCg0KREYgPC0gbWVyZ2UoREYsIElSRUEsIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJJUkVBX1ZFUiIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCiNDcmVhY2nDs24gZGUgdmFyaWFibGUgZGUgdmVyaWZpY2FjacOzbiBwYXJhIHJlZW1wbGF6byBkZSBOL0EncyANCmBgYA0KDQpgYGB7cn0NCkRGIDwtIG1lcmdlKERGLCBJUkVBLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiSVJFQSIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUV9DQpERiRJUkVBX1ZFUltpcy5uYShERiRJUkVBX1ZFUildIDwtIDANCkRGJElSRUFfVkVSW0RGJElSRUFfVkVSICE9IDBdIDwtICJTaSINCkRGJElSRUFfVkVSW0RGJElSRUFfVkVSID09ICIwIl0gPC0gIk5vIg0KREYkSVJFQVtpcy5uYShERiRJUkVBKV0gPC0gMA0KYGBgDQoNClVuaWVuZG8gbGEgdmFyaWFibGUgSW5ncmVzbyBSdWJybyBJTkdSRVNPUyBGSU5BTkNJRVJPUyAoSVJJRikNCg0KYGBge3J9DQpJUklGIDwtIGZpbHRlcihJVFMsIGBSdWJybyBJbmdyZXNvYCA9PSAiSU5HUkVTT1MgRklOQU5DSUVST1MiKQ0KSVJJRiA8LSBmaWx0ZXIoSVJJRixBw7FvICVpbiUgYygyMDIwLDIwMjEsMjAyMikpDQpJUklGIDwtIHNlbGVjdChJUklGLCAtJ1RpcG8gSW5ncmVzbycpDQpJUklGIDwtIHNlbGVjdChJUklGLCAtJ1J1YnJvIEluZ3Jlc28nKQ0KSVJJRiA8LSBzZWxlY3QoSVJJRiwgLSdQZXJpb2RvJykNCmBgYA0KDQpgYGB7cn0NCg0KREYgPC0gbWVyZ2UoREYsIElSSUYsIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJJUklGX1ZFUiIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCiNDcmVhY2nDs24gZGUgdmFyaWFibGUgZGUgdmVyaWZpY2FjacOzbiBwYXJhIHJlZW1wbGF6byBkZSBOL0EncyANCmBgYA0KDQpgYGB7cn0NCkRGIDwtIG1lcmdlKERGLCBJUklGLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiSVJJRiIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUV9DQpERiRJUklGX1ZFUltpcy5uYShERiRJUklGX1ZFUildIDwtIDANCkRGJElSSUZfVkVSW0RGJElSSUZfVkVSICE9IDBdIDwtICJTaSINCkRGJElSSUZfVkVSW0RGJElSSUZfVkVSID09ICIwIl0gPC0gIk5vIg0KREYkSVJJRltpcy5uYShERiRJUklGKV0gPC0gMA0KYGBgDQoNClVuaWVuZG8gbGEgdmFyaWFibGUgSW5ncmVzbyBSdWJybyBSRUVNQk9MU09TIChJUlIpDQoNCmBgYHtyfQ0KSVJSIDwtIGZpbHRlcihJVFMsIGBSdWJybyBJbmdyZXNvYCA9PSAiUkVFTUJPTFNPUyIpDQpJUlIgPC0gZmlsdGVyKElSUixBw7FvICVpbiUgYygyMDIwLDIwMjEsMjAyMikpDQpJUlIgPC0gc2VsZWN0KElSUiwgLSdUaXBvIEluZ3Jlc28nKQ0KSVJSIDwtIHNlbGVjdChJUlIsIC0nUnVicm8gSW5ncmVzbycpDQpJUlIgPC0gc2VsZWN0KElSUiwgLSdQZXJpb2RvJykNCg0KSVJSIDwtIGZpbHRlcihJUlIsIGBJbXBvcnRlIHBvciBTZXJ2aWNpb3NgICE9IDApDQpgYGANCg0KYGBge3J9DQoNCkRGIDwtIG1lcmdlKERGLCBJUlIsIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJJUlJfVkVSIiA9ICJJbXBvcnRlIHBvciBTZXJ2aWNpb3MiKQ0KI0NyZWFjacOzbiBkZSB2YXJpYWJsZSBkZSB2ZXJpZmljYWNpw7NuIHBhcmEgcmVlbXBsYXpvIGRlIE4vQSdzIA0KYGBgDQoNCmBgYHtyfQ0KREYgPC0gbWVyZ2UoREYsIElSUiwgYnkgPSBjKCJBw7FvIiwiTWVzIiwiQWVyb3B1ZXJ0byIsIkluZnJhZXN0cnVjdHVyYSIpLCBhbGw9VFJVRSkNCkRGIDwtIHJlbmFtZShERiwgIklSUiIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUV9DQpERiRJUlJfVkVSW2lzLm5hKERGJElSUl9WRVIpXSA8LSAwDQpERiRJUlJfVkVSW0RGJElSUl9WRVIgIT0gMF0gPC0gIlNpIg0KREYkSVJSX1ZFUltERiRJUlJfVkVSID09ICIwIl0gPC0gIk5vIg0KREYkSVJSW2lzLm5hKERGJElSUildIDwtIDANCmBgYA0KDQpDcmVhbmRvIGxhIHZhcmlhYmxlIE51bWVybyBkZSBQYXNhamVyb3MgdG90YWxlcyAoTlApDQoNCmBgYHtyfQ0KREYgJT4lIG11dGF0ZShOUCA9IE5QTiArIE5QSSkgLT4gREYNCiNOdW1lcm8gZGUgcGFzYWplcm9zIHRvdGFsZXMNCmBgYA0KDQpPcmdhbml6YW5kbyBlbCBERg0KDQpgYGB7cn0NCkRGJE1lcyA9IGZhY3RvcihERiRNZXMsIGxldmVscyA9YygiRW5lcm8iLCJGZWJyZXJvIiwiTWFyem8iLCJBYnJpbCIsIk1heW8iLCJKdW5pbyIsIkp1bGlvIiwiQWdvc3RvIiwiU2V0aWVtYnJlIiwiT2N0dWJyZSIsIk5vdmllbWJyZSIsIkRpY2llbWJyZSIpKQ0KREYgPC0gYXJyYW5nZShERiwgQcOxbywgTWVzKQ0KYGBgDQoNCiMjIExpbXBpZXphIGRlIGRhdG9zDQoNClNlIGNvbnNpZGVyYSBxdWUgZW4gY2FzbyBubyBzZSBjdWVudGUgY29uIGVsIG5vbWJyZSBkZWwgYWVyb3B1ZXJ0byBvIHN1IGluZnJhZXN0cnVjdHVyYSAoU2llbXByZSBkZWJlIHZlbmlyIGFjb21wYcOxYWRhIGRlbCBub21icmUpLCBsYSB1bmlkYWQgbXVlc3RyYWwgbm8gcG9kcsOhIGVudHJhciBhbCBhbsOhbGlzaXMgcHVlcyBwb3IgZWplbXBsbyBzaSBub3MgZGljZW4gY3VhbnRvIGdhbm8gdW4gYWVyb3B1ZXJ0byBkZXNjb25vY2lkbywgZXN0byBubyBub3MgZGlyw6EgbmFkYSB5IHBvciBlbGxvIGxhIGVsaW1pbmFyZW1vcy4NCg0KYGBge3J9DQoNCkRGJEFlcm9wdWVydG9bREYkQWVyb3B1ZXJ0byA9PSAnTm8gcHJlY2lzYSddIDwtIE5BDQpERiRBZXJvcHVlcnRvW0RGJEFlcm9wdWVydG8gPT0gJy0nXSA8LSBOQQ0KREYkSW5mcmFlc3RydWN0dXJhW0RGJEluZnJhZXN0cnVjdHVyYSA9PSAnLSddIDwtIE5BDQoNCkRGIDwtIGZpbHRlcihERiwgSW5mcmFlc3RydWN0dXJhICE9IGlzLm5hKCJJbmZyYWVzdHJ1Y3R1cmEiKSAmIEFlcm9wdWVydG8gIT0gaXMubmEoIkFlcm9wdWVydG8iKSkNCmBgYA0KDQpDYW1iaWFtb3MgbG9zIG5vbWJyZXMgZGUgbGEgdmFyaWFibGUgSW5mcmFlc3RydWN0dXJhOg0KDQpgYGB7cn0NCg0KREYgJT4lIG11dGF0ZSgiSW5mcmFlc3RydWN0dXJhIiA9DQogICAgICAgICAgICAgICAgICBpZmVsc2UoSW5mcmFlc3RydWN0dXJhPT0iQURQIiwgIkFlcm9wdWVydG9zIGRlbCBQZXLDuiBTLkEuIiwNCiAgICAgICAgICAgICAgICAgIGlmZWxzZShJbmZyYWVzdHJ1Y3R1cmE9PSJBQVAiLCAiQWVyb3B1ZXJ0b3MgQW5kaW5vcyBkZWwgUGVyw7ogUy5BLiIsDQogICAgICAgICAgICAgICAgICBpZmVsc2UoSW5mcmFlc3RydWN0dXJhPT0iQ09SIiwgIkNPUlBBQyBTLkEuIiwNCiAgICAgICAgICAgICAgICAgIGlmZWxzZShJbmZyYWVzdHJ1Y3R1cmE9PSJMQVAiLCAiTGltYSBBaXJwb3J0IFBhcnRuZXJzIFMuUi5MLiIsSW5mcmFlc3RydWN0dXJhKSkpKSkgLT4gREYNCmBgYA0KDQpFbGltaW5hbW9zIGxhcyB2YXJpYWJsZXMgdGVtcG9yYWxlczoNCg0KYGBge3J9DQpybShsaXN0ID0gYygiQUFETSIsIkFEQUgiLCJBREVQIiwiQUVIRSIsIkFMQyIsIkFPT0EiLCJJUkFEIiwiSVJFQSIsIklSSUYiLCJJUlMiLCJJVFMiLCJQSSIsIlBOIiwiVFAiLCJUVVVBSSIsIlRVVUFOIiwiSVJSIikpDQpgYGANCg0KRmluYWxtZW50ZSwgZWxpbWluYXJlbW9zIGFxdWVsbGFzIG9ic2VydmFjaW9uZXMgZG9uZGUgZXhpc3RhbiBOQSdzLiBBbnRlcyBkZSBoYWNlciBlc3RvIGVuY29udHJhbW9zIHF1ZSBsYSBtYXlvcsOtYSBkZSBhZXJvcHVlcnRvcyBkZSBsYSBpbmZyYWVzdHJ1Y3R1cmEgIkNPUlBBQyBTLkEuIiBubyBoYSByZXBvcnRhZG8gc3VzIGluZ3Jlc29zIHRvdGFsZXMgcG9yIGxvIHRhbnRvIGVzdGFyw61hbW9zIGRlamFuZG8gZnVlcmEgZGVsIGFuw6FsaXNpcyBhIGVzdG9zIGFlcm9wdWVydG9zLg0KDQpgYGB7cn0NCkRGIDwtIGRyb3BfbmEoREYpDQpgYGANCg0KYGBge3J9DQpzdW0oY29tcGxldGUuY2FzZXMoREYpKQ0KYGBgDQoNCiMjIEV4cG9ydGFuZG8gbGEgYmFzZSBkZSBkYXRvcw0KDQpgYGB7cn0NCndyaXRlX2NzdihERiwiQmFzZUxpbXBpYXYyLmNzdiIpDQoNCmBgYA0KDQojIEltcG9ydGFuZG8gbGEgYmFzZSBkYXRvcyBsaW1waWENCg0KYGBge3J9DQoNCnJtKGxpc3QgPSBscygpKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkocGx5cikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkodGlkeXIpDQoNCkRGIDwtIHJlYWRfY3N2KCJCYXNlTGltcGlhdjIuY3N2IikNCmBgYA0KDQojIFZhcmlhYmxlcw0KDQoqKkHDsW86KiogVmFyaWFibGUgY2F0ZWfDs3JpY2EgcXVlIGluZGljYSBlbCBhw7FvIGRlIGxhIHJlY29sZWNjacOzbiBkZSBpbmZvcm1hY2nDs24uDQoNCioqTWVzOioqIFZhcmlhYmxlIGNhdGVnw7NyaWNhIHF1ZSBpbmRpY2EgZWwgbWVzIGRlIGxhIHJlY29sZWNjacOzbiBkZSBpbmZvcm1hY2nDs24uDQoNCioqQWVyb3B1ZXJ0bzoqKiBWYXJpYWJsZSBjdWFsaXRhdGl2YSBxdWUgaW5kaWNhIGVsIGFlcm9wdWVydG8gZGVsIGN1YWwgc2UgcmVjb2xlY3RhIGxhIGluZm9ybWFjacOzbg0KDQoqKkluZnJhZXN0cnVjdHVyYToqKiBWYXJpYWJsZSBjdWFsaXRhdGl2YSBxdWUgaW5kaWNhIGVuIGFjcsOzbmltbyBhIHF1ZSBlbnRpZGFkIHBlcnRlbmVjZSBsYSBpbmZyYWVzdHJ1Y3R1cmEgZGVsIGFlcm9wdWVydG8gZGVsIGN1YWwgc2UgcmVjb2xlY3RhIGxhIGluZm9ybWFjacOzbi4NCg0KKipJbmZyYWVzdHJ1Y3R1cmE6KiogVmFyaWFibGUgY3VhbGl0YXRpdmEgcXVlIGluZGljYSBhIHF1ZSBlbnRpZGFkIHBlcnRlbmVjZSBsYSBpbmZyYWVzdHJ1Y3R1cmEgZGVsIGFlcm9wdWVydG8gZGVsIGN1YWwgc2UgcmVjb2xlY3RhIGxhIGluZm9ybWFjacOzbi4NCg0KKipJVDoqKiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgbG9zIGluZ3Jlc29zIHRvdGFsZXMgZW4gZG9sYXJlcyBxdWUgaGEgcmVnaXN0cmFkbyBlbCBhZXJvcHVlcnRvDQoNCioqSVI6KiogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGxvcyBpbmdyZXNvcyByZWd1bGFkb3MgZW4gZG9sYXJlcyBxdWUgaGEgcmVnaXN0cmFkbyBlbCBhZXJvcHVlcnRvDQoNCioqVFVVQU4qKjogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBxdWUgaGEgZ2VuZXJhZG8gbGEgKlRBUklGQSBVTklGSUNBREEgUE9SIFVTTyBERSBBRVJPUFVFUlRPIGRlIHRpcG8gbmFjaW9uYWwuKg0KDQoqKlRVVUFOKio6IFZhcmlhYmxlIGN1YW50aXRhdGl2YSBxdWUgcmVwcmVzZW50YSBlbCBpbmdyZXNvIGVuIGRvbGFyZXMgcXVlIGhhIGdlbmVyYWRvIGxhICpUQVJJRkEgVU5JRklDQURBIFBPUiBVU08gREUgQUVST1BVRVJUTyBkZSB0aXBvIGludGVybmFjaW9uYWwuKg0KDQoqKk5QSToqKiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgZWwgbnVtZXJvIGRlIHBhc2FqZXJvcyBpbnRlcm5hY2lvbmFsZXMgcXVlIGhhIHJlZ2lzdHJhZG8gZWwgYWVyb3B1ZXJ0bw0KDQoqKk5QTjoqKiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgZWwgbnVtZXJvIGRlIHBhc2FqZXJvcyBuYWNpb25hbGVzIHF1ZSBoYSByZWdpc3RyYWRvIGVsIGFlcm9wdWVydG8NCg0KKipJUkFEX1ZFUjoqKiBWYXJpYWJsZSBjYXRlZ8OzcmljYSBxdWUgcmVwcmVzZW50YSBzaSBlbCBhZXJvcHVlcnRvIG9idGllbmUgaW5ncmVzb3MgcG9yIGF0ZXJyaXphamUgeSBkZXNwZWd1ZS4NCg0KKipJUkFEOioqIFZhcmlhYmxlIGN1YW50aXRhdGl2YSBxdWUgcmVwcmVzZW50YSBlbCBpbmdyZXNvIGVuIGRvbGFyZXMgZGVsIGFlcm9wdWVydG8gcG9yIGF0ZXJyaXphamUgeSBkZXNwZWd1ZS4NCg0KKipBQURNX1ZFUjoqKiBWYXJpYWJsZSBjYXRlZ8OzcmljYSBxdWUgcmVwcmVzZW50YSBzaSBlbCBhZXJvcHVlcnRvIG9idGllbmUgaW5ncmVzb3MgcG9yIGVsIGFscXVpbGVyIGRlIMOhcmVhcyBkZSBtYW50ZW5pbWllbnRvLg0KDQoqKkFBRE06KiogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBwb3IgZWwgYWxxdWlsZXIgZGUgw6FyZWFzIGRlIG1hbnRlbmltaWVudG8uDQoNCioqQURFUF9WRVI6KiogVmFyaWFibGUgY2F0ZWfDs3JpY2EgcXVlIHJlcHJlc2VudGEgc2kgZWwgYWVyb3B1ZXJ0byBvYnRpZW5lIGluZ3Jlc29zIHBvciBlbCBhbHF1aWxlciBkZSBlc3BhY2lvcyBkZSBwdWJsaWNpZGFkLg0KDQoqKkFERVA6KiogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBwb3IgZWwgYWxxdWlsZXIgZGUgZXNwYWNpb3MgZGUgcHVibGljaWRhZC4NCg0KKipBTENfVkVSOioqIFZhcmlhYmxlIGNhdGVnw7NyaWNhIHF1ZSByZXByZXNlbnRhIHNpIGVsIGFlcm9wdWVydG8gb2J0aWVuZSBpbmdyZXNvcyBwb3IgZWwgYWxxdWlsZXIgZGUgbG9jYWxlcyBjb21lcmNpYWxlcy4NCg0KKipBTEM6KiogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBwb3IgZWwgYWxxdWlsZXIgZGUgbG9jYWxlcyBjb21lcmNpYWxlcy4NCg0KKipBT09BX1ZFUjoqKiBWYXJpYWJsZSBjYXRlZ8OzcmljYSBxdWUgcmVwcmVzZW50YSBzaSBlbCBhZXJvcHVlcnRvIG9idGllbmUgaW5ncmVzb3MgcG9yIGVsIGFscXVpbGVyIGRlIG9maWNpbmFzIGRlIG9wZXJhY2lvbmVzIGRlIGFlcm9sw61uZWFzLg0KDQoqKkFPT0E6KiogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBwb3IgZWwgYWxxdWlsZXIgZGUgb2ZpY2luYXMgZGUgb3BlcmFjaW9uZXMgZGUgYWVyb2zDrW5lYXMuDQoNCioqQURBSF9WRVI6KiogVmFyaWFibGUgY2F0ZWfDs3JpY2EgcXVlIHJlcHJlc2VudGEgc2kgZWwgYWVyb3B1ZXJ0byBvYnRpZW5lIGluZ3Jlc29zIHBvciBlbCBhbHF1aWxlciBkZSBhbG1hY2VuZXMvaGFuZ2FyZXMuDQoNCioqQURBSDoqKiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgZWwgaW5ncmVzbyBlbiBkb2xhcmVzIHBvciBlbCBhbHF1aWxlciBkZSBhbG1hY2VuZXMvaGFuZ2FyZXMuDQoNCioqQUVIRV9WRVI6KiogVmFyaWFibGUgY2F0ZWfDs3JpY2EgcXVlIHJlcHJlc2VudGEgc2kgZWwgYWVyb3B1ZXJ0byBvYnRpZW5lIGluZ3Jlc29zIHBvciBsYSBhdGVuY2nDs24gZW4gaG9yYXMgZXh0cmFzLg0KDQoqKkFFSEU6KiogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBwb3IgbGEgYXRlbmNpw7NuIGVuIGhvcmFzIGV4dHJhcy4NCg0KKipJUkVBX1ZFUjoqKiBWYXJpYWJsZSBjYXRlZ8OzcmljYSBxdWUgcmVwcmVzZW50YSBzaSBlbCBhZXJvcHVlcnRvIG9idGllbmUgaW5ncmVzb3MgcG9yIGVsIGVzdGFjaW9uYW1pZW50byBkZSBhZXJvbmF2ZXMuDQoNCioqSVJFQToqKiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgZWwgaW5ncmVzbyBlbiBkb2xhcmVzIHBvciBlbCBlc3RhY2lvbmFtaWVudG8gZGUgYWVyb25hdmVzLg0KDQoqKklSSUZfVkVSOioqIFZhcmlhYmxlIGNhdGVnw7NyaWNhIHF1ZSByZXByZXNlbnRhIHNpIGVsIGFlcm9wdWVydG8gb2J0aWVuZSBpbmdyZXNvcyBwb3IgcmVlbWJvbHNvIGVuIGluZ3Jlc29zIGZpbmFuY2llcm9zLg0KDQoqKklSSUY6KiogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBwb3IgcmVlbWJvbHNvIGVuIGluZ3Jlc29zIGZpbmFuY2llcm9zLg0KDQoqKklSUl9WRVI6KiogVmFyaWFibGUgY2F0ZWfDs3JpY2EgcXVlIHJlcHJlc2VudGEgc2kgZWwgYWVyb3B1ZXJ0byBvYnRpZW5lIGluZ3Jlc29zIHBvciByZWVtYm9sc29zLg0KDQoqKklSUjoqKiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgZWwgaW5ncmVzbyBlbiBkb2xhcmVzIHBvciByZWVtYm9sc29zLg0KDQoqKk5QOioqIFZhcmlhYmxlIGN1YW50aXRhdGl2YSBxdWUgcmVwcmVzZW50YSBlbCBudW1lcm8gZGUgcGFzYWplcm9zIHRvdGFsZXMgcXVlIGhhIHJlZ2lzdHJhZG8gZWwgYWVyb3B1ZXJ0by4NCg0KIyBEZXNjcmlwdG9yZXMgTnVtw6lyaWNvcw0KDQpgYGB7cn0NCmN2IDwtIGZ1bmN0aW9uKHgpew0KICAgIHJldHVybihzZCh4LCBuYS5ybT1UKS9tZWFuKHgsIG5hLnJtPVQpKQ0KfQ0KYGBgDQoNCmBgYHtyfQ0KdGFibGEgPC0gZGF0YS5mcmFtZShWYXJpYWJsZXMgPSBjKCdJVCcsICdOUE4nLCAnTlBJJywgJ1RVVUFOJywnVFVVQUknKSwNCiAgICAgICAgICAgICAgICAgICAgTWVkaWEgPSBjKG1lYW4oREYkSVQsIG5hLnJtPVQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW4oREYkTlBOLCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW4oREYkTlBJLCBuYS5ybT0gVCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFuKERGJFRVVUFOLCBuYS5ybT0gVCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFuKERGJFRVVUFJLCBuYS5ybT0gVCkpLA0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgTWVkaWFuYSA9IGMobWVkaWFuKERGJElULCBuYS5ybT1UKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhbihERiROUE4sIG5hLnJtID0gVCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYW4oREYkTlBJLCBuYS5ybT0gVCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhbihERiRUVVVBTiwgbmEucm0gPSBUKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhbihERiRUVVVBSSwgbmEucm09IFQpKSwgDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBEZXN2aWFjaW9uID0gYyhzZChERiRJVCwgbmEucm09VCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZChERiROUE4sIG5hLnJtID0gVCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZChERiROUEksIG5hLnJtPSBUKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkKERGJFRVVUFOLCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2QoREYkVFVVQUksIG5hLnJtPSBUKSksIA0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgVmFyaWFuemEgPSBjKHZhcihERiRJVCwgbmEucm0gPSBUKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIoREYkTlBOLCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhcihERiROUEksIG5hLnJtID0gVCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyKERGJFRVVUFOLCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhcihERiRUVVVBSSwgbmEucm0gPSBUKSksDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBSYW5nb0ludGVyY3VhcnRpbCA9IGMoSVFSKERGJElULCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJUVIoREYkTlBOLCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJUVIoREYkTlBJLCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJUVIoREYkVFVVQU4sIG5hLnJtID0gVCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIElRUihERiRUVVVBSSwgbmEucm0gPSBUKSksDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBDb2VmaWNpZW50ZVZhcmlhY2lvbiA9IGMoY3YoREYkSVQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN2KERGJE5QTiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3YoREYkTlBJKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN2KERGJE5QTiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3YoREYkTlBJKSkpDQp0YWJsYQ0KYGBgDQoNCkRlIGxhIHRhYmxhIHBvZGVtb3MgY29uc2VndWlyIGxhIHNpZ3VpZW50ZSBpbmZvcm1hY2nDs246DQoNCi0gICBMYSBlc2NhbGEgY29uIGxhIHF1ZSBzZSB0cmFiYWphIGVzIGJhc3RhbnRlIGdyYW5kZSwgZGUgYWjDrSBlbCBoZWNobyBxdWUgbGEgdmFyaWFuemEgeSBkZXN2aWFjacOzbiBzZWFuIHRhbiBncmFuZGUuDQoNCi0gICBUYW50byBsYSB2YXJpYW56YSBjb21vIGxhIGRlc3ZpYWNpw7NuIG5vcyBpbmRpY2FuIHF1ZSBsb3MgZGF0b3MgZGUgbG9zIEluZ3Jlc29zIFRvdGFsZXMsIGVsIE51bWVybyBkZSBQYXNhamVyb3MgTmFjaW9uYWxlcyB5IGVsIE51bWVybyBkZSBQYXNhamVyb3MgSW50ZXJuYWNpb25hbGVzIGVzdMOhbiBtdXkgZGlzcGVyc29zLg0KDQotICAgU2UgYXByZWNpYSB1biBmZW7Ds21lbm8gcXVlIGxhIG1lZGlhbmEgeSBlbCByYW5nbyBpbnRlcmN1YXJ0aWwgZGUgbGEgdmFyaWFibGUgUGFzYWplcm9zIGludGVybmFjaW9uYWxlcyBlcyAwLiBFc3RvIHF1aWVyZSBkZWNpciBxdWUgaGF5IG11Y2hvcyBhZXJvcHVlcnRvcyBsb3MgY3VhbGVzIG5vIHN1ZWxlbiByZWNpYmlyIHBhc2FqZXJvcyBpbnRlcm5hY2lvbmFsZXMuDQoNCiMjIE9iamV0aXZvIDENCg0KU2UgcmVhbGl6YXJhIGVsIGNvZWZpY2llbnRlIGRlIGNvcnJlbGFjacOzbiBlbnRyZSBjYWRhIHZhcmlhYmxlIHJ1YnJvIHkgbG9zIGluZ3Jlc29zIHRvdGFsZXMsIGFkZW3DoXMgc2UgY3JlYXLDoSB1biBtb2RlbG8gbGluZWFsIHF1ZSByZXByZXNlbnRlIGxhcyByZWxhY2lvbmVzLiBFc3RvIG5vcyBmYWNpbGl0YSBlbCB0cmFiYWphciBjb24gbGFzIDEyIHZhcmlhYmxlcyB5IHBvZGVyIHNpbnRldGl6YXIgbGEgaW5mb3JtYWNpw7NuIGVuIHVuIHNvbG8gZ3LDoWZpY28uDQoNCmBgYHtyfQ0KY29lZmNvciA8LSBjKDE6MTIpDQoNCiMgVFVVQU4gDQpjb2VmY29yWzFdIDwtY29yKERGJElULCBERiRUVVVBTiwgdXNlPSJjb21wbGV0ZS5vYnMiKQ0KDQojIFRVVUFJDQpjb2VmY29yWzJdIDwtY29yKERGJElULCBERiRUVVVBSSwgdXNlPSJjb21wbGV0ZS5vYnMiKQ0KDQojIElSQUQNCmNvZWZjb3JbM10gPC1jb3IoREYkSVQsIERGJElSQUQsIHVzZT0iY29tcGxldGUub2JzIikNCg0KDQojIEFBRE0NCmNvZWZjb3JbNF0gPC1jb3IoREYkSVQsIERGJEFBRE0sIHVzZT0iY29tcGxldGUub2JzIikNCg0KIyBBREVQDQpjb2VmY29yWzVdIDwtY29yKERGJElULCBERiRBREVQLCB1c2U9ImNvbXBsZXRlLm9icyIpDQoNCiMgQUxDDQpjb2VmY29yWzZdIDwtY29yKERGJElULCBERiRBTEMsIHVzZT0iY29tcGxldGUub2JzIikNCg0KIyBBT09BDQpjb2VmY29yWzddIDwtY29yKERGJElULCBERiRBT09BLCB1c2U9ImNvbXBsZXRlLm9icyIpDQoNCg0KIyBBREFIDQpjb2VmY29yWzhdIDwtY29yKERGJElULCBERiRBREFILCB1c2U9ImNvbXBsZXRlLm9icyIpDQoNCiMgQUVIRQ0KY29lZmNvcls5XSA8LWNvcihERiRJVCwgREYkQUVIRSwgdXNlPSJjb21wbGV0ZS5vYnMiKQ0KDQoNCiMgSVJFQQ0KY29lZmNvclsxMF0gPC1jb3IoREYkSVQsIERGJElSRUEsIHVzZT0iY29tcGxldGUub2JzIikNCg0KIyBJUklGDQpjb2VmY29yWzExXSA8LWNvcihERiRJVCwgREYkSVJJRiwgdXNlPSJjb21wbGV0ZS5vYnMiKQ0KDQojIElSUg0KY29lZmNvclsxMl0gPC1jb3IoREYkSVQsIERGJElSUiwgdXNlPSJjb21wbGV0ZS5vYnMiKQ0KDQpgYGANCg0KQWhvcmEgc2UgcHJvY2VkZXLDoSBhIGxhIHJldmlzacOzbiBkZSBsb3MgY29lZmljaWVudGVzIGRlIGNvcnJlbGFjacOzbiwgc2kgZXN0b3MgdGllbmVuIHVuIG7Dum1lcm8gbWF5b3IgYSAwLjc1IG8gbWVub3IgYSAtMC43NSBzZSBjb25zaWRlcmFyw6EgcXVlIHRpZW5lbiB1biBtb2RlbG8gbGluZWFsIHbDoWxpZG8uDQoNCmBgYHtyfQ0KY29lZmNvcg0KYGBgDQoNClNlIG9ic2VydmEgcXVlIGxvcyBjb2VmaWNpZW50ZXMgZGUgY29ycmVsYWNpw7NuIGNvbiBpbmRpY2VzICg0LCA1LCA2LCA3LCA4LCA5LCAxMSB5IDEyKSBubyBjdW1wbGVuIGNvbiBlbCBjcml0ZXJpbyByZXF1ZXJpZG8sIGVzIGRlY2lyIG5vIHBvc2VlbiB1bmEgY29ycmVsYWNpw7NuIGxpbmVhbCBjb24gbGEgdmFyaWFibGUgZGUgaW5ncmVzb3MgdG90YWxlcywgZXN0byB0YW1iacOpbiBub3MgaW5kaWNhIHF1ZSBzdXMgZGF0b3Mgc2UgZW5jdWVudHJhbiBtdXkgZGlzcGVyc29zIGVuIGNvbXBhcmFjacOzbiBjb24gbG9zIGRhdG9zIGRlIGxvcyBpbmdyZXNvcyB0b3RhbGVzLg0KDQpBaG9yYSBzZSByZWFsaXphcsOhIHkgZ3JhZmljYXLDoSBsb3MgbW9kZWxvcyBsaW5lYWxlcyBkZSBsYSB2YXJpYWJsZXMgcXVlIHByZXNlbnRhbiBidWVuYSBjb3JyZWxhY2nDs24uIEVzIGltcG9ydGFudGUgbm90YXIgcXVlIGVuIHRvZGFzIGVzdGFzIHNlIHRpZW5lIHVuYSBjb3JyZWxhY2nDs24gcG9zaXRpdmEsIGVzdG8gdGllbmUgc2VudGlkbyBwdWVzIGVudHJlIG3DoXMgZGluZXJvIGhheWEgZGUgYWxnw7puIHJ1YnJvLCBtw6FzIGRpbmVybyBoYWJyw6EgZW4gbG9zIGluZ3Jlc29zIHRvdGFsZXMNCg0KYGBge3J9DQoNCnBlbmRpZW50ZXMgPC0gYygxOjQpDQppbnRlcmNlcHRvcyA8LSBjKDE6NCkNCg0KIyBUVVVBTiANCm1vZGVsbyA8LSBsbShERiRJVCB+IERGJFRVVUFOLCBkYXRhPURGKQ0KcGVuZGllbnRlc1sxXSA8LSBhcy5udW1lcmljKG1vZGVsbyRjb2VmZmljaWVudHNbMl0pDQppbnRlcmNlcHRvc1sxXSA8LSBhcy5udW1lcmljKG1vZGVsbyRjb2VmZmljaWVudHNbMV0pDQoNCg0KIyBUVVVBSQ0KbW9kZWxvIDwtIGxtKERGJElUIH4gREYkVFVVQUksIGRhdGE9REYpDQpwZW5kaWVudGVzWzJdIDwtIGFzLm51bWVyaWMobW9kZWxvJGNvZWZmaWNpZW50c1syXSkNCmludGVyY2VwdG9zWzJdIDwtIGFzLm51bWVyaWMobW9kZWxvJGNvZWZmaWNpZW50c1sxXSkNCg0KDQojIElSQUQNCm1vZGVsbyA8LSBsbShERiRJVCB+IERGJElSQUQsIGRhdGE9REYpDQpwZW5kaWVudGVzWzNdIDwtIGFzLm51bWVyaWMobW9kZWxvJGNvZWZmaWNpZW50c1syXSkNCmludGVyY2VwdG9zWzNdIDwtIGFzLm51bWVyaWMobW9kZWxvJGNvZWZmaWNpZW50c1sxXSkNCg0KIyBJUklGDQptb2RlbG8gPC0gbG0oREYkSVQgfiBERiRJUkVBLCBkYXRhPURGKQ0KcGVuZGllbnRlc1s0XSA8LSBhcy5udW1lcmljKG1vZGVsbyRjb2VmZmljaWVudHNbMl0pDQppbnRlcmNlcHRvc1s0XSA8LSBhcy5udW1lcmljKG1vZGVsbyRjb2VmZmljaWVudHNbMV0pDQoNCmBgYA0KDQpgYGB7cn0NCmZpZyA8LSBwbG90X2x5KERGLCB4ID0gflRVVUFOLCB5ID0gfklULCANCiAgICAgICAgICAgICAgIHR5cGUgPSAic2NhdHRlciIsIA0KICAgICAgICAgICAgICAgbW9kZSA9ICJtYXJrZXJzIiwNCiAgICAgICAgICAgICAgIG5hbWU9IlRVVUFOIiwNCiAgICAgICAgICAgICAgIG1hcmtlciA9IGxpc3QoY29sb3IgPSAnI2VmNDc2ZicpDQogICAgICAgICAgICAgICApICU+JQ0KICAgICAgICBhZGRfdHJhY2UoeCA9IH5jKC1pbnRlcmNlcHRvc1sxXS9wZW5kaWVudGVzWzFdLDkwMDAwMDApLCB5ID0gYygwLHBlbmRpZW50ZXNbMV0qOTAwMDAwMCtpbnRlcmNlcHRvc1sxXSksIA0KICAgICAgICAgICAgICAgdHlwZSA9ICJzY2F0dGVyIiwNCiAgICAgICAgICAgICAgIG1vZGUgPSAibGluZXMiLA0KICAgICAgICAgICAgICAgbmFtZT0iVFVVQU4tbW9kZWwiLA0KICAgICAgICAgICAgICAgbWFya2VyID0gbGlzdChjb2xvciA9ICcjZWY0NzZmJykNCiAgICAgICAgICAgICAgICkgJT4lDQogICAgICAgIGFkZF90cmFjZShERiwgeCA9IH5UVVVBSSwgeSA9IH5JVCwgDQogICAgICAgICAgICAgICAgICB0eXBlID0gInNjYXR0ZXIiLCANCiAgICAgICAgICAgICAgICAgIG1vZGUgPSAibWFya2VycyIsDQogICAgICAgICAgICAgICAgICBuYW1lPSJUVVVBSSIsDQogICAgICAgICAgICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJyNmZmQxNjYnKQ0KICAgICAgICAgICAgICAgICAgKSAlPiUNCiAgICAgICAgYWRkX3RyYWNlKHggPSB+YygtaW50ZXJjZXB0b3NbMl0vcGVuZGllbnRlc1syXSw5MDAwMDAwKSwgeSA9IGMoMCxwZW5kaWVudGVzWzJdKjkwMDAwMDAraW50ZXJjZXB0b3NbMl0pLCANCiAgICAgICAgICAgICAgICAgIHR5cGUgPSAic2NhdHRlciIsIA0KICAgICAgICAgICAgICAgICAgbW9kZSA9ICJsaW5lcyIsDQogICAgICAgICAgICAgICAgICBuYW1lPSJUVVVBSS1tb2RlbCIsDQogICAgICAgICAgICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJyNmZmQxNjYnKQ0KICAgICAgICAgICAgICAgICAgKSAlPiUNCiAgICAgICAgYWRkX3RyYWNlKERGLCB4ID0gfklSQUQsIHkgPSB+SVQsIA0KICAgICAgICAgICAgICAgICAgdHlwZSA9ICJzY2F0dGVyIiwgDQogICAgICAgICAgICAgICAgICBtb2RlID0gIm1hcmtlcnMiLA0KICAgICAgICAgICAgICAgICAgbmFtZT0iSVJBRCIsDQogICAgICAgICAgICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJyMwNmQ2YTAnKQ0KICAgICAgICAgICAgICAgICAgKSAlPiUNCiAgICAgICAgYWRkX3RyYWNlKHggPSB+YygtaW50ZXJjZXB0b3NbM10vcGVuZGllbnRlc1szXSw5MDAwMDAwKSwgeSA9IGMoMCxwZW5kaWVudGVzWzNdKjkwMDAwMDAraW50ZXJjZXB0b3NbM10pLCANCiAgICAgICAgICAgICAgICAgIHR5cGUgPSAic2NhdHRlciIsIA0KICAgICAgICAgICAgICAgICAgbW9kZSA9ICJsaW5lcyIsDQogICAgICAgICAgICAgICAgICBuYW1lPSJJUkFELW1vZGVsIiwNCiAgICAgICAgICAgICAgICAgIG1hcmtlciA9IGxpc3QoY29sb3IgPSAnIzA2ZDZhMCcpDQogICAgICAgICAgICAgICAgICApICU+JQ0KICAgICAgICBhZGRfdHJhY2UoREYsIHg9IH5JUkVBLCB5ID0gfklULCANCiAgICAgICAgICAgICAgICAgIHR5cGU9InNjYXR0ZXIiLCANCiAgICAgICAgICAgICAgICAgIG1vZGU9Im1hcmtlcnMiLA0KICAgICAgICAgICAgICAgICAgbmFtZT0iSVJFQSIsDQogICAgICAgICAgICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJyMxMThhYjInKQ0KICAgICAgICAgICAgICAgICAgKSAlPiUNCiAgICAgICAgYWRkX3RyYWNlKHggPSB+YygtaW50ZXJjZXB0b3NbNF0vcGVuZGllbnRlc1s0XSw5MDAwMDAwKSwgeSA9IGMoMCxwZW5kaWVudGVzWzRdKjkwMDAwMDAraW50ZXJjZXB0b3NbNF0pLCANCiAgICAgICAgICAgICAgICAgIHR5cGU9InNjYXR0ZXIiLCANCiAgICAgICAgICAgICAgICAgIG1vZGU9ImxpbmVzIiwNCiAgICAgICAgICAgICAgICAgIG5hbWU9IklSRUEtbW9kZWwiLA0KICAgICAgICAgICAgICAgICAgbWFya2VyID0gbGlzdChjb2xvciA9ICcjMTE4YWIyJykNCiAgICAgICAgICAgICAgICAgICkgJT4lDQogICAgICAgIGxheW91dCh4YXhpcyA9IGxpc3QoIHRpdGxlID0gIkluZ3Jlc29zIFVTJCIpLA0KICAgICAgICB5YXhpcyA9IGxpc3QoIHRpdGxlID0gIkluZ3Jlc29zIHRvdGFsZXMgVVMkIikpDQoNCg0KZmlnDQogICAgDQpgYGANCg0KVXNhbmRvIGVsIGdyw6FmaWNvIGludGVyYWN0aXZvIHBvZGVtb3MgYWlzbGFyIGNhZGEgdW5vIGRlIGVzdG9zIHJ1YnJvcyB5IHZlciBzdSBjb21wb3J0YW1pZW50byBqdW50byBhIHN1IG1vZGVsby4gQXF1w60gdmVtb3MgY29tbyBlbCBtb2RlbG8gZGUgSVJFQSB0aWVuZSBsYSBtYXlvciBwZW5kaWVudGUgc2lnbmlmaWNhbmRvIHF1ZSBsYSBtYXlvciBwYXJ0ZSBkZSBsb3MgaW5ncmVzb3MgdG90YWxlcyBlbiBwcm9wb3JjacOzbiB2ZW5kcsOtYSBkZSBlc3RlIHJ1YnJvLCBzaW4gZW1iYXJnbywgb2JzZXJ2YW1vcyBxdWUgbGEgZGF0YSBubyBlcyBjb25ncnVlbnRlLCBlbCBtb2RlbG8gbm8gc2UgYXByb3hpbWEgY29ycmVjdGFtZW50ZSBwZXNlIGEgcXVlIHZpbW9zIHF1ZSBvYnR1dm8gdW4gY29lZmljaWVudGUgZGUgY29ycmVsYWNpw7NuIG1heW9yIGEgMC43NS4gQ29uIGVzdG8gc2UgZGVqYSBlbiBldmlkZW5jaWEgcXVlIGVsIGNvZWZpY2llbnRlIGRlIGNvcnJlbGFjacOzbiBsaW5lYWwgbm8gZXMgZWwgw7puaWNvIHF1ZSBkZWJlbW9zIHRvbWFyIGVuIGN1ZW50YSBhbCByZWFsaXphciB1biBtb2RlbG8gZGUgcmVncmVzacOzbiBsaW5lYWwuIEVudG9uY2VzLCBkZWphbmRvIGRlIGxhZG8gYSBJUkVBLCBzZSBhcHJlY2lhIHF1ZSBsb3MgbW9kZWxvcyB5IGxhIGRhdGEgZGUgVFVVQU4sIFRVVUFJIGUgSVJBRCBzZSBhcHJveGltYW4gYmFzdGFudGUgYmllbiwgc2llbmRvLCBlbCBkZSBtYXlvciBwZW5kaWVudGUsIElSQUQuIFBvciBsbyBxdWUgY29uY2x1aW1vcyBxdWUgbGEgbWF5b3IgcGFydGUgZGUgbG9zIGluZ3Jlc29zIHRvdGFsZXMgZGVwZW5kZW4gZGUgbG9zIGluZ3Jlc29zIG9idGVuaWRvcyBwb3IgZWwgaW1wb3J0ZSBkZSBzZXJ2aWNpb3MgZGUgKipBdGVyaXphamUgeSBkZXNwZWd1ZSoqLg0KDQojIyBPYmpldGl2byAyDQoNCmBgYHtyfQ0KDQpwbG90KERGJElSRUEsIERGJElULCB4bGFiID0gIk51bWVybyBkZSBwYXNhamVyb3MgKG1pbGVzKSIsIHlsYWIgPSAiSW5ncmVzb3MgdG90YWxlcyAobWlsbG9uZXMgZGUgVVMkKSIsIGNvbD0iZGFya2dyZWVuIiwgcGNoPSLigKIiKQ0KYWJsaW5lKGE9aW50ZXJjZXB0b3NbNF0sIGI9IHBlbmRpZW50ZXNbNF0pDQoNCg0KYGBgDQoNCmBgYHtyfQ0KcGxvdF9seSh5ID1+IERGJElULCB4ID1+REYkSVJFQSwgdHlwZT0ic2NhdHRlciIpICU+JQ0KICAgIA0KYGBgDQoNCiMjIyBOdW1lcm8gZGUgUGFzYWplcm9zIHZzIEluZ3Jlc29zIFRvdGFsZXMNCg0KYGBge3J9DQpwbG90KERGJE5QLzEwMDAsIERGJElULzEwMDAwMDAsIHhsYWIgPSAiTnVtZXJvIGRlIHBhc2FqZXJvcyAobWlsZXMpIiwgeWxhYiA9ICJJbmdyZXNvcyB0b3RhbGVzIChtaWxsb25lcyBkZSBVUyQpIiwgY29sPSJkYXJrZ3JlZW4iLCBwY2g9IuKAoiIsIHhsaW0gPSBjKDAsMjAwMCkpDQoNCmBgYA0KDQpDb21lbnphbW9zIGNvbXBhcmFuZG8gZWwgbnVtZXJvIGRlIHBhc2FqZXJvcyBlbiBtaWxlcyB0b3RhbGVzLCBzdW1hIGRlIHBhc2FqZXJvcyBpbnRlcm5hY2lvbmFsZXMgeSBuYWNpb25hbGVzLCBjb24gbG9zIGluZ3Jlc29zIHRvdGFsZXMgZGUgY2FkYSBhZXJvcHVlcnRvIGVuIGRldGVybWluYWRvIG1lcyB5IGHDsW8gZW4gbWlsbG9uZXMgZGUgZG9sYXJlcy4gQSBzaW1wbGUgdmlzdGEgc2UgcHVlZGUgdmVyIHVuIGNpZXJ0byB0aXBvIGRlIHJlbGFjacOzbiBsaW5lYWwsIHNpbiBlbWJhcmdvIHRlbmVtb3MgcXVlIGNvbXByb2JhcmxvLiBVc2FyZW1vcyBlbCBjb2VmaWNpZW50ZSBkZSBjb3JyZWxhY2nDs24geWEgcXVlIGVzdGUgbm8gdG9tYSBlbiBjdWVudGEgbGEgZXNjYWxhIGRlIGxhcyB1bmlkYWRlcywgcGVyZmVjdG8gcGFyYSBudWVzdHJvIGVzdHVkaW8uDQoNCmBgYHtyfQ0KY29yKERGJElULCBERiROUCwgdXNlPSJjb21wbGV0ZS5vYnMiKQ0KYGBgDQoNCkNvbiBsYSBpbmZvcm1hY2nDs24gc3VtaW5pc3RyYWRhIGRlbCBjb2VmaWNpZW50ZSBkZSBjb3JyZWxhY2nDs24gc2UgZGVkdWNlIHF1ZSBsYSByZWxhY2nDs24gbGluZWFsIGVudHJlIGVsIG51bWVybyBkZSBwYXNhamVyb3MgeSBsb3MgaW5ncmVzb3MgdG90YWxlcyBlcyBidWVuYSwgY2FzaSBwZXJmZWN0YSB5IGFzY2VuZGVudGUuIEVzIGRlY2lyIGxvcyBpbmdyZXNvcyB0b3RhbGVzIGF1bWVudGFyYW4gZW4gY3VhbnRvIGF1bWVudGUgZWwgbnVtZXJvIGRlIHBhc2FqZXJvcy4NCg0KQWhvcmEgY3JlYXJlbW9zIHVuIG1vZGVsbyBkZSByZWdyZXNpw7NuIGxpbmVhbC4NCg0KYGBge3J9DQoNCm1vZGVsbyA9IGxtKERGJElUIH4gREYkTlAsIGRhdGE9REYpDQptb2RlbG8NCg0KZCA8LSBkYXRhLmZyYW1lKCJYIj1ERiROUC8xMDAwLCAiWSI9REYkSVQvMTAwMDAwMCkNCm1vZGVsbyA9IGxtKGQkWSB+IGQkWCwgZGF0YT1kKQ0KbW9kZWxvDQpgYGANCg0KSGVtb3MgY3JlYWRvIGRvcyBtb2RlbG9zIHF1ZSBlbiByZWFsaWRhZCBzb24gZWwgbWlzbW8gcGVybyBhIGRpZmVyZW50ZXMgZXNjYWxhcy4gRWwgcHJpbWVybyBub3Mgc2lydmUgcGFyYSB1c2FyIGRpcmVjdGFtZW50ZSBlbCBudW1lcm8gZGUgcGFzYWplcm9zIHkgbG9zIGluZ3Jlc29zIHRvdGFsZXMgZW4gZG9sYXJlcy4gRWwgc2VndW5kbyBwYXJhIHVzYXIgZWwgbnVtZXJvIGRlIHBhc2FqZXJvcyBlbiBtaWxlcyB5IGNvbnNlZ3VpciBsb3MgaW5ncmVzb3MgdG90YWxlcyBlbiBtaWxsb25lcyBkZSBkb2xhcmVzLiBBbWJvcyBtb2RlbG9zIG5vcyBwZXJtaXRlbiBhcHJveGltYXIsIHByZWRlY2lyIGxvcyBpbmdyZXNvcyB0b3RhbGVzIGRlIHVuIGFlcm9wdWVydG8gZW4gZGV0ZXJtaW5hZG8gbWVzIHkgYcOxbyB1c2FuZG8gbGEgY2FudGlkYWQgZGUgcGFzYWplcm9zIHRvdGFsZXMgcXVlIGxsZXZvIGVuIGVsIG1pc21vIGxhcHNvIGRlIHRpZW1wby4NCg0KYGBge3J9DQpwbG90KERGJE5QLzEwMDAsIERGJElULzEwMDAwMDAsIHhsYWIgPSAiTnVtZXJvIGRlIHBhc2FqZXJvcyAobWlsZXMpIiwgeWxhYiA9ICJJbmdyZXNvcyB0b3RhbGVzIChtaWxsb25lcyBkZSBVUyQpIiwgY29sPSJkYXJrZ3JlZW4iLCBwY2g9IuKAoiIsIHhsaW0gPSBjKDAsMjAwMCkpDQphYmxpbmUoYT0gLTAuMTQ4OTAsIGI9MC4wMTY0NiwgY29sPSJncmVlbiIpDQpgYGANCg0KIyMjIE51bWVybyBkZSBQYXNhamVyb3MgTmFjaW9uYWxlcyBlIEludGVybmFjaW9uYWxlcyB2cyBJbmdyZXNvcyBUb3RhbGVzDQoNCmBgYHtyfQ0KcGFyKG1mcm93PWMoMSwyKSkNCg0KcGxvdChERiROUE4vMTAwMCwgREYkSVQvMTAwMDAwMCwgeGxhYiA9ICJOdW1lcm8gZGUgcGFzYWplcm9zIG5hY2lvbmFsZXMgKG1pbGVzKSIsIHlsYWIgPSAiSW5ncmVzb3MgdG90YWxlcyAobWlsbG9uZXMgZGUgVVMkKSIsIGNvbD0icmVkIiwgcGNoPSLigKIiKQ0KDQpwbG90KERGJE5QSS8xMDAwLCBERiRJVC8xMDAwMDAwLCB4bGFiID0gIk51bWVybyBkZSBwYXNhamVyb3MgaW50ZXJuYWNpb25hbGVzIChtaWxlcykiLCB5bGFiID0gIkluZ3Jlc29zIHRvdGFsZXMgKG1pbGxvbmVzIGRlIFVTJCkiLCBjb2w9ImJsdWUiLCBwY2g9IuKAoiIpDQpgYGANCg0KQWhvcmEgdmFtb3MgYSBhbmFsaXphciBsYSByZWxhY2nDs24gZGUgbG9zIHRpcG9zIGRlIHBhc2FqZXJvcyBjb24gbG9zIGluZ3Jlc29zIHRvdGFsZXMuIERlIG51ZXZvIHVzYXJlbW9zIGVsIGNvZWZpY2llbnRlIGRlIGNvcnJlbGFjacOzbiB0YW50byBwYXJhIGxvcyBwYXNhamVyb3MgbmFjaW9uYWxlcyBjb21vIGludGVybmFjaW9uYWxlcy4NCg0KYGBge3J9DQpjb3IoREYkSVQsIERGJE5QTiwgdXNlPSJjb21wbGV0ZS5vYnMiKQ0KY29yKERGJElULCBERiROUEksIHVzZT0iY29tcGxldGUub2JzIikNCmBgYA0KDQpEZSBsb3MgY29lZmljaWVudGVzIGRhZG9zIHNlIGVuY3VlbnRyYSBxdWU6DQoNCi0gICBBbWJvcyBkZW11ZXN0cmFuIHF1ZSB0YW50byBsb3MgcGFzYWplcm9zIG5hY2lvbmFsZXMgY29tbyBpbnRlcm5hY2lvbmFsZXMgcG9zZWVuIHVuYSBidWVuYSB5IGFzY2VuZGVudGUgcmVsYWNpw7NuIGxpbmVhbCBjb24gbG9zIGluZ3Jlc29zIHRvdGFsZXMuDQotICAgQW1ib3Mgc29uIG1lbm9yZXMgYWwgKipjb3IqKiBkZSBsb3MgcGFzYWplcm9zIHRvdGFsZXMgY29uIGxvcyBpbmdyZXNvcyB0b3RhbGVzLiBJbmRpY2EgcXVlIHNpIHNlIHVzYSBzb2xvIGEgbG9zIHBhc2FqZXJvcyBuYWNpb25hbGVzIG8gc29sbyBhIGxvcyBpbnRlcm5hY2lvbmFsZXMgcGFyYSBhcHJveGltYXIgbG9zIGluZ3Jlc29zIHRvdGFsZXMsIHNlIHRlbmRyw6EgdW5hIHByZWNpc2nDs24gbWVub3IgYSBxdWUgc2kgc2UgdXNhcsOhIGxhIHN1bWEgZGUgYW1ib3MuDQotICAgRWwgKipjb3IqKiBkZSBsb3MgcGFzYWplcm9zIGludGVybmFjaW9uYWxlcyBlcyBsaWdlcmFtZW50ZSBzdXBlcmlvciBhbCBkZSBsb3MgcGFzYWplcm9zIG5hY2lvbmFsZXMsIG1vc3RyYW5kbyBxdWUgc3UgcmVsYWNpw7NuIGxpbmVhbCBjb24gbG9zIGluZ3Jlc29zIHRvdGFsZXMgZXMgbGlnZXJhbWVudGUgbcOhcyBhY29yZGUgcXVlIGxhIHJlbGFjacOzbiBsaW5lYWwgZGUgbG9zIHBhc2FqZXJvcyBuYWNpb25hbGVzLg0KDQpBaG9yYSBjb25zdHJ1eWFtb3MgbG9zIG1vZGVsb3MgZGUgcmVncmVzacOzbiBsaW5lYWwgcGFyYSBjYWRhIHVuby4NCg0KYGBge3J9DQoNCm1vZGVsbyA9IGxtKERGJElUIH4gREYkTlBOLCBkYXRhPURGKQ0KbW9kZWxvDQoNCmQgPC0gZGF0YS5mcmFtZSgiWCI9REYkTlBOLzEwMDAsICJZIj1ERiRJVC8xMDAwMDAwKQ0KbW9kZWxvID0gbG0oZCRZIH4gZCRYLCBkYXRhPWQpDQptb2RlbG8NCg0KbW9kZWxvID0gbG0oREYkSVQgfiBERiROUEksIGRhdGE9REYpDQptb2RlbG8NCg0KZCA8LSBkYXRhLmZyYW1lKCJYIj1ERiROUEkvMTAwMCwgIlkiPURGJElULzEwMDAwMDApDQptb2RlbG8gPSBsbShkJFkgfiBkJFgsIGRhdGE9ZCkNCm1vZGVsbw0KDQpybShkKQ0KYGBgDQoNClZlbW9zIHF1ZSBsb3MgbW9kZWxvcyBkaWZpZXJlbiBlbiB1bmEgY2FudGlkYWQgY29uc2lkZXJhYmxlIGVuIGN1YW50byBhIHN1IHBlbmRpZW50ZSwgc2luIGVtYmFyZ28sIHN1IGludGVyY2VwdG8gZXMgYmFzdGFudGUgc2ltaWxhciwgdmFtb3MgYSBncmFmaWNhciBlc3RvcyBtb2RlbG9zLg0KDQpgYGB7cn0NCnBhcihtZnJvdz1jKDEsMikpDQoNCnBsb3QoREYkTlBOLzEwMDAsIERGJElULzEwMDAwMDAsIHhsYWIgPSAiTnVtZXJvIGRlIHBhc2FqZXJvcyBuYWNpb25hbGVzIChtaWxlcykiLCB5bGFiID0gIkluZ3Jlc29zIHRvdGFsZXMgKG1pbGxvbmVzIGRlIFVTJCkiLCBjb2w9InJlZCIsIHBjaD0i4oCiIikNCmFibGluZShhPSAtMC4zNjAzMywgYj0wLjAyNDUxLCBjb2w9IiNmNzI1ODUiKQ0KDQpwbG90KERGJE5QSS8xMDAwLCBERiRJVC8xMDAwMDAwLCB4bGFiID0gIk51bWVybyBkZSBwYXNhamVyb3MgaW50ZXJuYWNpb25hbGVzIChtaWxlcykiLCB5bGFiID0gIkluZ3Jlc29zIHRvdGFsZXMgKG1pbGxvbmVzIGRlIFVTJCkiLCBjb2w9ImJsdWUiLCBwY2g9IuKAoiIpDQphYmxpbmUoYT0gMC4zMTk5NiwgYj0wLjA0NzcyLCBjb2w9IiMwMDc3YjYiKQ0KYGBgDQoNCiMjIE9iamV0aXZvIDMNCg0KUGFyYSBhdmVyaWd1YXIgY3VhbCBlcyBlbCBhZXJvcHVlcnRvIHF1ZSBtYXlvciB0csOhZmljbyB5IGVsIGFlcm9wdWVydG8gcXVlIG1heW9yZXMgaW5ncmVzb3MgZ2VuZXJhIGVuIGVsIFBlcsO6IGVuIGxvcyBhw7FvcyAoMjAyMCwgMjAyMSB5IDIwMjIpLCBhbmFsaXphcmVtb3MgbGEgZGlzdHJpYnVjacOzbiBkZSBJbmdyZXNvcyBUb3RhbGVzIHBsYW50ZWFuZG8gZ3LDoWZpY29zIHkgcmVsYWNpb25lcy4NCg0KIyMjIEFuYWxpemFuZG8gbGEgZGlzdHJpYnVjacOzbiBkZSBJbmdyZXNvcyBUb3RhbGVzDQoNCmBgYHtyfQ0KcGxvdF9seSh4ID0gfkRGJElULzEwMDAwMDAsDQogICAgICAgIHR5cGU9Imhpc3RvZ3JhbSIsDQogICAgICAgIGNvbG9yID0gfkRGJEluZnJhZXN0cnVjdHVyYSwNCiAgICAgICAgbmJpbnN4ID0gNDANCiAgICAgICAgKSU+JQ0KbGF5b3V0KHlheGlzID0gbGlzdCggdGl0bGUgPSAiRnJlY3VlbmNpYSIgKSwNCiAgICB4YXhpcyA9IGxpc3QoIHRpdGxlID0gIkluZ3Jlc29zIHRvdGFsZXMgKE1pbGxvbmVzIGRlIFVTJCkiLA0KICAgICAgICAgICAgICAgICAgbnRpY2tzID0gMjApKQ0KYGBgDQoNCkdyYWNpYXMgYWwgaGlzdG9ncmFtYSBzZSBkaWNlIHF1ZSBsb3MgZGF0b3MgZGUgbG9zIGluZ3Jlc29zIHRvdGFsZXMgc29uIHRvdGFsbWVudGUgYXNpbcOpdHJpY29zIHkgc2UgZW5jdWVudHJhbiBhY3VtdWxhZG9zIGVuIHVuIGludGVydmFsbyBkZSAwIC0gMC44IG1pbGxvbmVzIGRlIGRvbGFyZXMuIEVzIGRlY2lyIGxhIG1heW9yw61hIGRlIGFlcm9wdWVydG9zIGRldGVybWluYWRvcyBlbiBjaWVydG8gbWVzIHkgY2llcnRvIGHDsW8gcG9zZWUgdW5vcyBpbmdyZXNvcyB0b3RhbGVzIGRlIGVudHJlIDAgeSAwLjggbWlsbG9uZXMgZGUgZG9sYXJlcy4gRXN0byBwdWVkZSBvY3VycmlyIGRlYmlkbyBhIGRhdG9zIGF0w61waWNvcywgY29uc3RydXlhbW9zIHVuIEJveHBsb3QgcGFyYSBxdWUgbm9zIGF5dWRlLg0KDQpgYGB7cn0NCnBsb3RfbHkoREYsIHg9fkRGJElULzEwMDAwMDAsDQogICAgICAgICAgICB0eXBlID0gImJveCIpJT4lDQpsYXlvdXQoDQogICAgeGF4aXMgPSBsaXN0KCB0aXRsZSA9ICJJbmdyZXNvcyB0b3RhbGVzIChNaWxsb25lcyBkZSBVUyQpIikpDQpgYGANCg0KVXNhbmRvIHVuIEJveHBsb3Qgc2ltcGxlIHNlIGNvbXBydWViYSBjb21vIGxvcyBkYXRvcyBkZSBsb3MgaW5ncmVzb3MgdG90YWxlcyBlc3TDoW4gZGVtYXNpYWRvIGRpc3BlcnNvcyBncmFjaWFzIGEgY2llcnRhIGNhbnRpZGFkIGRlIGRhdG9zIGF0w61waWNvcy4gQWhvcmEgZXMgbmVjZXNhcmlvIGF2ZXJpZ3VhciBkZSBkb25kZSBwcm92aWVuZW4gZXN0b3MgZGF0b3MgYXTDrXBpY29zIHkgcXVlIG5vcyBxdWllcmVuIGRlY2lyLiBQYXJhIGVsbG8gY3JlYXJlbW9zIGRpZmVyZW50ZXMgQm94cGxvdHMgYmFzYWRvcyBlbiBtZXNlcywgaW5mcmFlc3RydWN0dXJhcyB5IGFlcm9wdWVydG9zLg0KDQpgYGB7cn0NCnBsb3RfbHkoREYsIHggPSB+SVQvMTAwMDAwMCwgDQogICAgICAgIHkgPSB+TWVzLCANCiAgICAgICAgY29sb3I9IH5NZXMsIA0KICAgICAgICB0eXBlPSJib3giKSAlPiUNCmxheW91dCh5YXhpcyA9IGxpc3QoIHRpdGxlID0gIk1lcyIpLA0KICAgIHhheGlzID0gbGlzdCggdGl0bGUgPSAiSW5ncmVzb3MgdG90YWxlcyAoTWlsbG9uZXMgZGUgVVMkKSIpKQ0KYGBgDQoNCkNvbiBlc3RlIGdyw6FmaWNvIHBvZGVtb3MgZGVzY2FydGFyIHF1ZSBsb3MgZGF0b3MgYXTDrXBpY29zIHByb3ZlbmdhbiBkZSB1biBvIHZhcmlvcyBtZXNlcyBlbiBlc3BlY8OtZmljby4NCg0KYGBge3J9DQpwbG90X2x5KERGLCB4ID0gfklULzEwMDAwMDAsIA0KICAgICAgICB5ID0gfkluZnJhZXN0cnVjdHVyYSwgDQogICAgICAgIGNvbG9yPSB+SW5mcmFlc3RydWN0dXJhLCANCiAgICAgICAgdHlwZT0iYm94IikgJT4lDQpsYXlvdXQoeWF4aXMgPSBsaXN0KCB0aXRsZSA9ICJJbmZyYWVzdHJ1Y3R1cmEiKSwNCiAgICB4YXhpcyA9IGxpc3QoIHRpdGxlID0gIkluZ3Jlc29zIHRvdGFsZXMgKE1pbGxvbmVzIGRlIFVTJCkiKSkNCmBgYA0KDQpFbiBlc3RlIGdyw6FmaWNvIHNlIG9ic2VydmEgY29tbyBMaW1hIEFpcnBvcnQgUGFydG5lcnMgUy5SLkwgcmViYXNhIHBvciBtdWNobyBhIGxhcyBvdHJhcyBpbmZyYWVzdHJ1Y3R1cmFzIGVuIGN1YW50byBhIGluZ3Jlc29zIHRvdGFsZXMgc2UgcmVmaWVyZS4gQXF1w60gcG9kZW1vcyB5YSBzYWJlciBxdWUgZXNvcyBkYXRvcyBhdMOtcGljb3MgZGUgaW5ncmVzb3MgZXN0w6FuIGdlbmVyYWRvcyBlbiBzdSBncmFuIG1heW9yw61hIHBvciBsYSBpbmZyYWVzdHJ1Y3R1cmEgTGltYSBBaXJwb3J0IFBhcnRuZXJzIFMuUi5MLiBBZGVtw6FzIGVzIGltcG9ydGFudGUgbWVuY2lvbmFyIHF1ZSBsYSBpbmZyYWVzdHJ1Y3R1cmEgQ09SIG5vIGFwYXJlY2UgZW4gbGEgZ3LDoWZpY2EgcHVlcyBubyBoYSBkZWNsYXJhZG8gbmluZ8O6biBpbmdyZXNvIHRvdGFsLg0KDQpPdHJvcyBkYXRvcyBhIGNvbnNpZGVyYXI6DQoNCi0gRWwgYm94cGxvdCBkZSBMaW1hIEFpcnBvcnQgUGFydG5lcnMgUy5SLkwgc2UgdmUgcGVyZmVjdG8gY3VhbmRvIGxvIGFpc2xhbW9zLCBtdWVzdHJhIHF1ZSBubyBwb3NlZSBuaW5nw7puIGRhdG8gYXTDrXBpY28uDQoNCi0gRWwgYm94cGxvdCBkZSBBZXJvcHVlcnRvcyBkZWwgUGVyw7ogUy5BIGFsIGFpc2xhcmxvIHNlIG9ic2VydmEgY29tbyBsYSBjYWphIGVzIGJhc3RhbnRlIHBlcXVlw7FhIHkgcG9zZWUgbXVjaG9zIGRhdG9zIGF0w61waWNvcyBxdWUgc29uIG1heW9yZXMgYSBsYSBtZWRpYW5hLg0KDQotIEVsIGJveHBsb3QgZGUgQWVyb3B1ZXJ0b3MgQW5kaW5vcyBkZWwgUGVyw7ogUy5BIG11ZXN0cmEgdW4gYmlnb3RlIHBlZ2FkbyBhbCBjdWFydGlsIDI1JSwgZGVtb3N0cmFuZG8gcXVlIGxvcyBkYXRvcyBkZWwgMjUlIGluZmVyaW9yIHNvbiBpZ3VhbGVzIG8gbXV5IGNlcmNhbm9zLiBBc2ltaXNtbyBzZSBvYnNlcnZhbiBkYXRvcyBhdGlwaWNvcyBtYXlvcmVzIGEgbGEgbWVkaWFuYS4NCg0KYGBge3J9DQpwbG90X2x5KERGLCB4ID0gfklULzEwMDAwMDAsIA0KICAgICAgICB5ID0gfkFlcm9wdWVydG8sIA0KICAgICAgICBjb2xvcj0gfkFlcm9wdWVydG8sIA0KICAgICAgICB0eXBlPSJib3giDQogICAgICAgICkgJT4lDQpsYXlvdXQoeWF4aXMgPSBsaXN0KCB0aXRsZSA9ICJBZXJvcHVlcnRvcyIpLA0KICAgIHhheGlzID0gbGlzdCggdGl0bGUgPSAiSW5ncmVzb3MgdG90YWxlcyAoTWlsbG9uZXMgZGUgVVMkKSIpKQ0KYGBgDQoNCkdyYWNpYXMgYSBsb3MgMyBncsOhZmljb3MgcG9kZW1vcyBjb25jbHVpciBxdWU6DQoNCi0gICBFbCBhZXJvcHVlcnRvIGRlIExpbWEgY3V5YSBlbnRpZGFkIHByZXN0YWRvcmEgZXMgbGEgTEFQLCBlcyBsYSByZXNwb25zYWJsZSBkZSBsb3MgZGF0b3MgYXTDrXBpY29zIHkgYWRlbcOhcyBlcyBlbCBxdWUgbcOhcyBpbmdyZXNvcyB0b3RhbGVzIGdlbmVyYS4NCg0KLSAgIEVsIGJveHBsb3QgZGVsIGFlcm9wdWVydG8gTGltYSBhaXNsYWRvIGVuIGJhc2UgYSBsb3MgaW5ncmVzb3MgdG90YWxlcyBtdWVzdHJhIHF1ZSBleGlzdGUgZGF0b3MgbWVub3JlcyBhIGxhIG1lZGlhbmEgbcOhcyBzaW4gZW1iYXJnbyBzdSBtaW5pbW8gc2UgYXByw7N4aW1hIHBvciBtdWNobyBhbCBxdWFydGlsIGluZmVyaW9yIDI1JS4gICANCg0KLSAgIExhIGluZnJhZXN0cnVjdHVyYSBMQVAgdHJhYmFqYSBlbiBMaW1hIHkgc2UgcmVmaWVyZSBhbCBBZXJvcHVlcnRvIEludGVybmFjaW9uYWwgSm9yZ2UgQ2jDoXZlei4gRXN0byBub3MgcXVpZXJlIGRlY2lyIHF1ZSBlbiBlbCBQZXLDuiwgZWwgYWVyb3B1ZXJ0byBxdWUgZ2VuZXJhIG3DoXMgaW5ncmVzb3MgZXMgZWwgSm9yZ2UgQ2jDoXZlei4NCg0KIyMjIE51bWVybyBkZSBQYXNhamVyb3MgdnMgQWVyb3B1ZXJ0b3MNCg0KYGBge3J9DQpwbG90X2x5KERGLHkgPSB+TlAvMTAwMCwNCiAgICAgICAgeCA9IH5hcy5mYWN0b3IoQWVyb3B1ZXJ0byksIA0KICAgICAgICB0eXBlPSJiYXIiLA0KICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yPWMoImxpZ2h0Ymx1ZSIpKQ0KICAgICAgICApJT4lDQogICAgbGF5b3V0KHhheGlzID0gbGlzdCggdGl0bGUgPSAiQWVyb3B1ZXJ0b3MiKSwNCiAgICB5YXhpcyA9IGxpc3QoIHRpdGxlID0gIk51bWVybyBkZSBwYXNhamVyb3MgKG1pbGVzKSIpKQ0KYGBgDQoNCkNvbiBlc3RhIGdyw6FmaWNvIHNlIGNvcnJvYm9yYSBxdWUgZWwgQWVyb3B1ZXJ0byBkZSBMaW1hIChBZXJvcHVlcnRvIEludGVybmFjaW9uYWwgSm9yZ2UgQ2jDoXZleikgZ2VuZXJhIGxhIG1heW9yIGNhbnRpZGFkIGRlIGluZ3Jlc29zIHkgYWRlbcOhcyByZWNpYmUgYSBsYSBtYXlvciBjYW50aWRhZCBkZSBwYXNhamVyb3MgcmVzcGVjdG8gYWwgcmVzdG8gZGVsIFBlcsO6LiBPdHJvcyBhZXJvcHVlcnRvcyBub3RhYmxlcyBzb24gQ3VzY28sIEFyZXF1aXBhIGUgSXF1aXRvcyBkb25kZSBDdXNjbyBlcyBlbCBxdWUgbcOhcyBwYXNhamVyb3MgcmVjaWJlIGZ1ZXJhIGRlIExpbWEuIFNlIHByb2NlZGUgYSBkaWJ1amFyIGVsIG51bWVybyBkZSBwYXNhamVyb3MsIGxvcyBpbmdyZXNvcyB0b3RhbGVzIHkgbG9zIGFlcm9wdWVydG9zLg0KDQpgYGB7cn0NCnBsb3RfbHkoREYseCA9IH5OUC8xMDAwLA0KICAgICAgICB5ID0gfklULzEwMDAwMDAsIA0KICAgICAgICB0eXBlPSJzY2F0dGVyIiwNCiAgICAgICAgY29sb3IgPSB+YXMuZmFjdG9yKEFlcm9wdWVydG8pDQogICAgICAgICkNCmBgYA0KDQpFbCBncsOhZmljbyBub3MgZGVqYSBlbiBjbGFybyBsYSBlc3RyZWNoYSByZWxhY2nDs24gZGUgbGEgY2FudGlkYWQgZGUgcGFzYWplcm9zIGNvbiBsYSBkZSBpbmdyZXNvcyBxdWUgcG9zZWUgZWwgYWVyb3B1ZXJ0byBkZSBMaW1hIHkgY29tbyBlc3RlIHNvYnJlc2FsZSBwb3IgbXVjaG8gZGVsIHJlc3RvIGRlIGFlcm9wdWVydG9zLiBTZSBjb25jbHV5ZSBxdWUgbG9zIGRhdG9zIGF0w61waWNvcyBwcm92ZW5pZW50ZXMgZGUgaW5ncmVzb3MgdG90YWxlcyBlcmFuIHkgbm9zIGNvbnRhYmFuIHNvYnJlIGxhcyBwZWN1bGlhcmlkYWRlcyBkZWwgY2FzbyBMaW1hLg0KDQojIyMgSW5ncmVzb3MgVCBVIFUgQSBUb3RhbCB2cyBJbmdyZXNvcyBUb3RhbGVzDQoNClNlIGVsaWdpw7MgbGEgY29tcGFyYWNpw7NuIGRlIGxhcyBUIFUgVSBBLCBwb3JxdWUgZXN0YSBlcyBsYSBUQVJJRkEgVU5JRklDQURBIFBPUiBVU08gREUgQUVST1BVRVJUTywgZXMgZGVjaXIgZXMgdW5hIHRhcmlmYSBxdWUgY29tbyBjb25zdW1pZG9yZXMgZGViZW1vcyBkZSBwYWdhci4gRWwgb2JqZXRpdm8gYXF1w60gZXMgYW5hbGl6YXIgY3VhbnRvIGRlIGxvcyBpbmdyZXNvcyB0b3RhbGVzIHByb3ZpZW5lbiBkaXJlY3RhbWVudGUgZGUgbG9zIGJvbHNpbGxvcyBkZSBsb3MgcGFzYWplcm9zLg0KDQpgYGB7cn0NCnBsb3QoKERGJFRVVUFOLzEwMDAwMDAgKyBERiRUVVVBSS8xMDAwMDAwKSwgREYkSVQvMTAwMDAwMCwgeGxhYiA9ICJJbmdyZXNvcyBUVVVBIChtaWxsb25lcyBkZSBVUyQpIiwgeWxhYiA9ICJJbmdyZXNvcyB0b3RhbGVzIChtaWxsb25lcyBkZSBVUyQpIiwgY29sPSIjOTI2YzE1IiwgcGNoPSLigKIiKQ0KDQpgYGANCg0KQ29tZW56YW1vcyBjb21wYXJhbmRvIGVsIG51bWVybyBkZSBwYXNhamVyb3MgZW4gbWlsZXMgdG90YWxlcywgc3VtYSBkZSBwYXNhamVyb3MgaW50ZXJuYWNpb25hbGVzIHkgbmFjaW9uYWxlcywgY29uIGxvcyBpbmdyZXNvcyB0b3RhbGVzIGRlIGNhZGEgYWVyb3B1ZXJ0byBlbiBkZXRlcm1pbmFkbyBtZXMgeSBhw7FvIGVuIG1pbGxvbmVzIGRlIGRvbGFyZXMuIEEgc2ltcGxlIHZpc3RhIHNlIHB1ZWRlIHZlciB1biBjaWVydG8gdGlwbyBkZSByZWxhY2nDs24gbGluZWFsLCBzaW4gZW1iYXJnbyB0ZW5lbW9zIHF1ZSBjb21wcm9iYXJsby4gVXNhcmVtb3MgZWwgY29lZmljaWVudGUgZGUgY29ycmVsYWNpw7NuIHlhIHF1ZSBlc3RlIG5vIHRvbWEgZW4gY3VlbnRhIGxhIGVzY2FsYSBkZSBsYXMgdW5pZGFkZXMsIHBlcmZlY3RvIHBhcmEgbnVlc3RybyBlc3R1ZGlvLg0KDQpgYGB7cn0NCmNvcihERiRJVCwgREYkVFVVQUkgKyBERiRUVVVBTiwgdXNlPSJjb21wbGV0ZS5vYnMiKQ0KYGBgDQoNClRlbmVtb3MgdW4gY29lZmljaWVudGUgZGUgY29ycmVsYWNpw7NuIHF1ZSBlc3RhIG11eSBwcsOzeGltbyBhIDEsIGVzIGRlY2lyIGVzdGEgcmVsYWNpw7NuIGVzIGNhc2kgcGVyZmVjdGFtZW50ZSBsaW5lYWwgeSBjb24gdGVuZGVuY2lhIGFzY2VuZGVudGUuDQoNCkFob3JhIGNyZWFyZW1vcyB1biBtb2RlbG8gZGUgcmVncmVzacOzbiBsaW5lYWwuDQoNCmBgYHtyfQ0KVFVVQSA8LSBERiRUVVVBSStERiRUVVVBTg0KbW9kZWxvID0gbG0oREYkSVQgfiBUVVVBLCBkYXRhPURGKQ0KbW9kZWxvDQoNCmQgPC0gZGF0YS5mcmFtZSgiWCI9IChERiRUVVVBSSArIERGJFRVVUFOKS8xMDAwMDAsICJZIj1ERiRJVC8xMDAwMDAwKQ0KbW9kZWxvID0gbG0oZCRZIH4gZCRYLCBkYXRhPWQpDQptb2RlbG8NCg0Kcm0oZCkNCmBgYA0KDQpEZWwgbW9kZWxvIGNyZWFkbyBzZSBvYnRpZW5lIGVsIGludGVyY2VwdG8sIGVzIGRlY2lyIGN1YW5kbyBsYSBUVVVBIHZhbGRyw6EgY2VybyB5IGxhIHBlbmRpZW50ZSwgZW4gZXN0ZSBjYXNvIGVzIHJlbGF0aXZhbWVudGUgYmFqYSBwZXJvIGFzY2VuZGVudGUuDQoNCmBgYHtyfQ0KcGxvdCgoREYkVFVVQU4rREYkVFVVQUkpLzEwMDAwMCwgREYkSVQvMTAwMDAwMCwgeGxhYiA9ICJJbmdyZXNvcyBUVVVBIHRvdGFsIChtaWxsb25lcyBkZSBVUyQpIiwgeWxhYiA9ICJJbmdyZXNvcyB0b3RhbGVzIChtaWxsb25lcyBkZSBVUyQpIiwgY29sPSIjOTI2YzE1IiwgcGNoPSLigKIiKQ0KYWJsaW5lKGE9IDAuMTU1NywgYj0wLjIxOTAsIGNvbD0iI2M5YTIyNyIpDQpgYGANCg0KRGV0YWxsYW1vcyBlbnRvbmNlcyBxdWUgbG9zIGluZ3Jlc29zIHRvdGFsZXMgZ3VhcmRhbiB1bmEgYWx0YSByZWxhY2nDs24gY29uIGxvcyBpbmdyZXNvcyBnZW5lcmFkb3MgcG9yIGxhcyBUVVVBIHkgZGVwZW5kZW4gZW4gZ3JhbiBtZWRpZGEgZGUgZXN0YXMsIGVyZ28gbGEgY2FudGlkYWQgZGUgcGFzYWplcm9zLg0KDQojIyBPYmpldGl2byA0DQoNCkFob3JhIGhhcmVtb3MgdW4gYW7DoWxpc2lzIGRlIGxhIHBhbmRlbWlhIHkgcG9zdHBhbmRlbWlhIGRlIGxvcyBpbmdyZXNvcyB0b3RhbGVzIGVuIGxvcyBhZXJvcHVlcnRvcyBkZWwgUGVyw7ogZW4gbG9zIGHDsW9zICgyMDIwLDIwMjEgeSAyMDIyKQ0KDQojIyMgUGFuZGVtaWEgdnMgUG9zdFBhbmRlbWlhDQoNCmBgYHtyfQ0KREYyMDIwIDwtIGZpbHRlcihERiwgREYkQcOxbz09IjIwMjAiKQ0KREYyMDIxIDwtIGZpbHRlcihERiwgREYkQcOxbz09IjIwMjEiKQ0KREYyMDIyIDwtIGZpbHRlcihERiwgREYkQcOxbz09IjIwMjIiKQ0KDQpERjIwMjAgJT4lIGdyb3VwX2J5KE1lcyxBw7FvKSAlPiUgc3VtbWFyaXNlKElUID0gc3VtKElULCBuYS5ybT1UUlVFKSwgTlAgPSBzdW0oTlAsIG5hLnJtID0gVFJVRSkpIC0+IERGMjAyMA0KDQpERjIwMjEgJT4lIGdyb3VwX2J5KE1lcyxBw7FvKSAlPiUgc3VtbWFyaXNlKElUID0gc3VtKElULCBuYS5ybT1UUlVFKSwgTlAgPSBzdW0oTlAsIG5hLnJtID0gVFJVRSkpIC0+IERGMjAyMQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KREYyMDIyICU+JSBncm91cF9ieShNZXMsQcOxbykgJT4lIHN1bW1hcmlzZShJVCA9IHN1bShJVCwgbmEucm09VFJVRSksIE5QID0gc3VtKE5QLCBuYS5ybSA9IFRSVUUpKSAtPiBERjIwMjINCg0KDQpgYGANCg0KYGBge3J9DQpwbG90X2x5KHkgPSB+REYyMDIwJElULzEwMDAwMDAsDQogICAgICAgIHggPSB+REYyMDIwJE1lcywgDQogICAgICAgIHR5cGU9ImJhciIsDQogICAgICAgIG5hbWU9IjIwMjAiLA0KICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJyM1N2NjOTknKQ0KICAgICAgICApJT4lIA0KDQogICAgDQogICAgYWRkX3RyYWNlKHkgPSB+REYyMDIxJElULzEwMDAwMDAsDQogICAgICAgIHggPSB+REYyMDIxJE1lcywgDQogICAgICAgIHR5cGU9ImJhciIsDQogICAgICAgIG5hbWU9IjIwMjEiLA0KICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJyMzOGEzYTUnKQ0KICAgICAgICApJT4lDQogICAgDQogICAgDQogICAgYWRkX3RyYWNlKHkgPSB+REYyMDIyJElULzEwMDAwMDAsDQogICAgICAgIHggPSB+REYyMDIyJE1lcywgDQogICAgICAgIHR5cGU9ImJhciIsDQogICAgICAgIG5hbWU9IjIwMjIiLA0KICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJyMyMjU3N2EnKQ0KICAgICAgICApJT4lDQogICAgDQogICAgDQogICAgbGF5b3V0KHhheGlzID0gbGlzdCggdGl0bGUgPSAiTWVzZXMiKSwNCiAgICB5YXhpcyA9IGxpc3QoIHRpdGxlID0gIkluZ3Jlc29zIHRvdGFsZXMgKE1pbGxvbmVzIGRlIFVTJCkiLA0KICAgIG50aWNrcyA9IDEwLA0KICAgIHJhbmdlID0gbGlzdCgwLDQ1KSksDQogICAgDQogICAgYmFybW9kZT0iZ3JvdXAiKQ0KYGBgDQoNCkRlbCBncsOhZmljbyBkZSBiYXJyYXMgcG9kZW1vcyBvYnNlcnZhcjoNCg0KLSAgIExhIGRpc3RyaWJ1Y2nDs24gZGUgbG9zIGluZ3Jlc29zIHRvdGFsZXMgZW4gYmFzZSBhIGxvcyBtZXNlcyBkZWwgYcOxby4NCg0KLSAgIEV4aXN0ZSB1bmEgYXNpbWV0cmlhIG5vdGFibGUgZW50cmUgbG9zIGRhdG9zIGVuIGVsIGHDsW8gMjAyMC4gRXN0YSBhc2ltZXRyaWEgc2UgZXhwbGljYSBwb3IgZWwgc3VyZ2ltaWVudG8gZGVsIENvdmlkLTE5LiBMb3MgaW5ncmVzb3MgYmFqYXJvbiBiYXN0YW50ZSBlbiBwcm9wb3JjacOzbiBhIGxhIG1lZGlhLg0KDQotICAgVW4gcGF0csOzbiBkZSBjcmVjaW1pZW50byBzb2JyZSBsb3MgaW5ncmVzb3MgdG90YWxlcyBkZXBlbmRpZW5kbyBkZSBsb3MgbWVzZXMuIEVuIGFsZ3Vub3MgbWVzZXMgbG9zIGluZ3Jlc29zIHRvdGFsZXMgc29uIGVzcGVyYWRvIGEgc2VyIG1heW9yZXMgcXVlIGVuIG90cm9zIG1lc2VzLCB1bm8gZGUgbG9zIGZhY3RvcmVzIHF1ZSBwdWVkZW4gaW5mbHVpciBlbiBlc3RvIHNvbiBsYXMgdmFjYWNpb25lcyBwdWVzIGVzdMOhbiBlc3RyZWNoYW1lbnRlIHJlbGFjaW9uYXMgY29uIGVsIG7Dum1lcm8gZGUgcGFzYWplcm9zIGEgYWJvcmRhciBlbiB1biBhZXJvcHVlcnRvLg0KDQpgYGB7cn0NCg0KcGxvdF9seSgpICU+JQ0KICAgIGFkZF90cmFjZSh5ID0gfkRGMjAyMCRJVC8xMDAwMDAwLA0KICAgICAgICB4ID0gfkRGMjAyMCRNZXMsIA0KICAgICAgICB0eXBlPSJzY2F0dGVyIiwNCiAgICAgICAgbW9kZT0ibGluZXMrbWFya2VycyIsDQogICAgICAgIG5hbWU9IjIwMjAiLA0KICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJyM1N2NjOTknKSwNCiAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAnIzU3Y2M5OScpLA0KICAgICAgICBmaWxsID0gInRvbmV4dHkiLA0KICAgICAgICBmaWxsY29sb3IgPSAncmdiYSgxOTcsMjM3LDIxMSwwLjMpJw0KICAgICAgICApJT4lDQogICAgYWRkX3RyYWNlKERGMjAyMSwgeSA9IH5ERjIwMjEkSVQvMTAwMDAwMCwNCiAgICAgICAgeCA9IH5ERjIwMjEkTWVzLCANCiAgICAgICAgdHlwZT0ic2NhdHRlciIsDQogICAgICAgIG1vZGU9ImxpbmVzK21hcmtlcnMiLA0KICAgICAgICBuYW1lPSIyMDIxIiwNCiAgICAgICAgbWFya2VyID0gbGlzdChjb2xvciA9ICcjMzhhM2E1JyksDQogICAgICAgIGxpbmUgPSBsaXN0KGNvbG9yID0gJyMzOGEzYTUnKSwNCiAgICAgICAgZmlsbCA9ICJ0b25leHR5IiwNCiAgICAgICAgZmlsbGNvbG9yID0gJ3JnYmEoMTA2LDE2NiwxNjksMC4zKScNCiAgICAgICAgKSU+JQ0KICAgIGFkZF90cmFjZSh5ID0gfkRGMjAyMiRJVC8xMDAwMDAwLA0KICAgICAgICB4ID0gfkRGMjAyMiRNZXMsIA0KICAgICAgICB0eXBlPSJzY2F0dGVyIiwNCiAgICAgICAgbW9kZT0ibGluZXMrbWFya2VycyIsDQogICAgICAgIG5hbWU9IjIwMjIiLA0KICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJyMyMjU3N2EnKSwNCiAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAnIzIyNTc3YScpLA0KICAgICAgICBmaWxsID0gInRvbmV4dHkiLA0KICAgICAgICBmaWxsY29sb3IgPSAncmdiYSg2OCwxMDIsMTIyLDAuMyknDQogICAgICAgICklPiUNCiAgICANCiAgICBsYXlvdXQoeGF4aXMgPSBsaXN0KCB0aXRsZSA9ICJNZXNlcyIpLA0KICAgICAgICAgICB0aXRsZSA9ICJFdm9sdXRpdm8gSW5ncmVzb3MiLA0KICAgIHlheGlzID0gbGlzdCggdGl0bGUgPSAiSW5ncmVzb3MgdG90YWxlcyAoTWlsbG9uZXMgZGUgVVMkKSIsIA0KICAgICAgICAgICAgICAgICAgcmFuZ2UgPSBsaXN0KDAsNDUpKQ0KICAgICkNCg0KYGBgDQoNCmBgYHtyfQ0KcGxvdF9seSgpICU+JQ0KICAgIGFkZF90cmFjZSh5ID0gfkRGMjAyMCROUC8xMDAwLA0KICAgICAgICB4ID0gfkRGMjAyMCRNZXMsIA0KICAgICAgICB0eXBlPSJzY2F0dGVyIiwNCiAgICAgICAgbW9kZT0ibGluZXMrbWFya2VycyIsDQogICAgICAgIG5hbWU9IjIwMjAiLA0KICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJyNFMDlGM0UnKSwNCiAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAnI0UwOUYzRScpLA0KICAgICAgICBmaWxsID0gInRvbmV4dHkiLA0KICAgICAgICBmaWxsY29sb3IgPSAncmdiYSgyMjUsMTgzLDEyMywwLjMpJw0KICAgICAgICApJT4lDQogICAgYWRkX3RyYWNlKERGMjAyMSwgeSA9IH5ERjIwMjEkTlAvMTAwMCwNCiAgICAgICAgeCA9IH5ERjIwMjEkTWVzLCANCiAgICAgICAgdHlwZT0ic2NhdHRlciIsDQogICAgICAgIG1vZGU9ImxpbmVzK21hcmtlcnMiLA0KICAgICAgICBuYW1lPSIyMDIxIiwNCiAgICAgICAgbWFya2VyID0gbGlzdChjb2xvciA9ICcjOUUyQTJCJyksDQogICAgICAgIGxpbmUgPSBsaXN0KGNvbG9yID0gJyM5RTJBMkInKSwNCiAgICAgICAgZmlsbCA9ICJ0b25leHR5IiwNCiAgICAgICAgZmlsbGNvbG9yID0gJ3JnYmEoMTU4LDcyLDc0LDAuMyknDQogICAgICAgICklPiUNCiAgICBhZGRfdHJhY2UoeSA9IH5ERjIwMjIkTlAvMTAwMCwNCiAgICAgICAgeCA9IH5ERjIwMjIkTWVzLCANCiAgICAgICAgdHlwZT0ic2NhdHRlciIsDQogICAgICAgIG1vZGU9ImxpbmVzK21hcmtlcnMiLA0KICAgICAgICBuYW1lPSIyMDIyIiwNCiAgICAgICAgbWFya2VyID0gbGlzdChjb2xvciA9ICcjNTQwQjBFJyksDQogICAgICAgIGxpbmUgPSBsaXN0KGNvbG9yID0gJyM1NDBCMEUnKSwNCiAgICAgICAgZmlsbCA9ICJ0b25leHR5IiwNCiAgICAgICAgZmlsbGNvbG9yID0gJ3JnYmEoODcsNDUsNDcsMC4zKScNCiAgICAgICAgKSU+JQ0KICAgIA0KICAgIGxheW91dCh4YXhpcyA9IGxpc3QoIHRpdGxlID0gIk1lc2VzIiksDQogICAgICAgICAgIHRpdGxlID0gIkV2b2x1dGl2byBQYXNhamVyb3MiLA0KICAgIHlheGlzID0gbGlzdCggdGl0bGUgPSAiTnVtZXJvIGRlIFBhc2FqZXJvcyAoTWlsZXMpIikpDQpgYGANCg0KRGUgbG9zIGdyw6FmaWNvcyBldm9sdXRpdm9zIHBvZGVtb3MgYXByZWNpYXI6DQoNCi0gICBDb21vIGVzIGVsIGNvbXBvcnRhbWllbnRvIGRlIGxvcyBpbmdyZXNvcyB0b3RhbGVzIGZyZW50ZSBhIGxvcyBtZXNlcyB5IGEgbG9zIGHDsW9zIG1hcmNhZG9zIHBvciBsYSBwYW5kZW1pYS4NCg0KLSAgIEVuIGVsIG1lcyBkZSBGZWJyZXJvIGRlbCBhw7FvIDIwMjAgY29taWVuemEgdW5hIGNhw61kYSBkcsOhc3RpY2EgZW4gbG9zIGluZ3Jlc29zIGhhc3RhIEFicmlsIGRlbCBtaXNtbyBhw7FvIGRvbmRlIGNvbWllbnphIGEgZXN0YWJpbGl6YXJzZS4gRXN0ZSBwZXJpb2RvIGNvaW5jaWRlIGNvbiBsYSBhcGFyaWNpw7NuIGRlbCBDb3ZpZC0xOSBlbiBQZXLDuiB5IGVsIGVzdGFibGVjaW1pZW50byBkZSBsYXMgbWVkaWRhcyBkZSBjb25maW5hbWllbnRvLiBFbCBjb25maW5hbWllbnRvIGluZGljYSBxdWUgZWwgbsO6bWVybyBkZSBwYXNhamVyb3Mgc2UgcmVkdWNlIGVuIGdyYW4gcHJvcG9yY2nDs24uIEVzdGEgY2F1c2EgdGFtYmnDqW4gc2UgcHVlZGUgb2JzZXJ2YXIgZW4gZWwgZXZvbHV0aXZvIGRlIHBhc2FqZXJvcyB5IGVsIGNvbW8gc3UgbsO6bWVybyBkZSBjYWUgaGFzdGEgMCBvIGNhc2kgMC4gTG9zIGFlcm9wdWVydG8gdHV2aWVyb24gY29uc2VjdWVuY2lhcyBxdWUgdGFyZGFyb24gbXVjaG8gZW4gZGlzaXBhcnNlIE11ZXN0cmEgZGUgZWxsbyBlcyBjb21vIHNlIHRhcmTDsyAyIGHDsW9zIHkgNSBtZXNlcyBwYXJhIHZvbHZlciBhIHVuIHB1bnRvIHNpbWlsYXIgYWwgZGUgRmVicmVybyAyMDIwIGVuIGluZ3Jlc29zIHRvdGFsZXMuDQoNCg0KICAgIGBgYHtyfQ0KDQogICAgcm91bmQoMTAwIC0gKChmaWx0ZXIoREYyMDIwLCBNZXMgPT0gIkFicmlsIikkSVQvMTAwMDAwMCApLyggZmlsdGVyKERGMjAyMCwgTWVzID09ICJGZWJyZXJvIikkSVQvMTAwMDAwMCkgKiAxMDApICwyKQ0KDQogICAgcm91bmQoIC0gZmlsdGVyKERGMjAyMCwgTWVzID09ICJBYnJpbCIpJElULzEwMDAwMDAgICsgZmlsdGVyKERGMjAyMCxNZXMgPT0gIkZlYnJlcm8iKSRJVC8xMDAwMDAwLCAyKQ0KICAgIGBgYA0KDQotICAgTGEgcMOpcmRpZGEgZGVsIG1lcyBkZSBBYnJpbCBkZWwgMjAyMCByZXNwZWN0byBhbCBtZXMgZGUgRmVicmVybyBkZWwgMjAyMCBmdWUgZGVsIDg2LjY4JSBzdXBvbmllbmRvIHVuYSBkaWZlcmVuY2lhIGRlIDMxLjc2IG1pbGxvbmVzIGRlIGRvbGFyZXMuDQoNCi0gICBBIHBhcnRpciBkZWwgbWVzIGRlIEFicmlsIHNlIGVzdGFiaWxpemFuIGxvcyBpbmdyZXNvcyBkZWwgYcOxbyAyMDIwLiBFc3RvcyBzb24gYmFqb3MgcGVybyBzZSBvYnNlcnZhIHVuYSB0ZW5kZW5jaWEgYXNjZW5kZW50ZS4gVGVuZGVuY2lhIHF1ZSBjb250aW51YSBlbiBsb3MgYcOxb3MgMjAyMSB5IDIwMjIgYSBtZWRpZGEgcXVlIGVsIGNvbmZpbmFtaWVudG8gc2UgbGV2YW50YSwgbGEgcGFuZGVtaWEgc2UgY29udHJvbGEgeSBlbCBudW1lcm8gZGUgcGFzYWplcm9zIGF1bWVudGEuDQoNCg0KIyMgQ29uY2x1c2nDs24NCg0KQSByYXrDs24gZGUgcmVzdW1lbiwgZW4gbnVlc3RybyBhbsOhbGlzaXMgc29icmUgbG9zIGZhY3RvcmVzIGluZmx1eWVudGVzIGVuIGxvcyBpbmdyZXNvcyB0b3RhbGVzIGRlIGxvcyBhZXJvcHVlcnRvcyBzZSBncsOhZmljbyBsYSBkaXN0cmlidWNpw7NuIGRlIGxvcyBpbmdyZXNvcyB0b3RhbGVzLCBsYXMgZGlmZXJlbnRlcyByZWxhY2lvbmVzIGVudHJlIHZhcmlhYmxlcyB0YWxlcyBjb21vIGxhIMO6bHRpbWEgdmlzdGEgKEluZ3Jlc29zIFRVVUEgdnMgSW5ncmVzb3MgVG90YWxlcyksIChjYW50aWRhZCBkZSBwYXNhamVyb3MgeSBhZXJvcHVlcnRvcykuIEFzaW1pc21vIG9ic2VydmFtb3MgeSBkZXNjcmliaW1vcyBlbCBjb21wb3J0YW1pZW50byBldm9sdXRpdm8gZGUgbG9zIGluZ3Jlc29zIHRvdGFsZXMgcmVzcGVjdG8gYSBsb3MgYcOxb3Mgdml2aWRvcyBlbiBwYW5kZW1pYSB5IHBvcy1wYW5kZW1pYS4gRmluYWxtZW50ZSwgY29uIGxhIGluZm9ybWFjacOzbiByZWNvbGVjdGFkYSB5IGVsIGVzdHVkaW8gcmVhbGl6YWRvIHNlIGVuY29udHLDsyBxdWUgbG9zIGluZ3Jlc29zIHRvdGFsZXMgZ2VuZXJhZG9zIHBvciBsb3MgYWVyb3B1ZXJ0b3MgZW4gZWwgUGVyw7ogZGVwZW5kZW4gYWx0YW1lbnRlIGVuIGxvcyBjb25zdW1pZG9yZXMgbyBwYXNhamVyb3MsIHNpZW5kbyBsYSBUVVVBIHkgZWwgSVJBRCBsb3MgZWplbXBsb3MgbcOhcyBjbGFyb3MgZGUgZWxsby4NCg0KIyBSZWZlcmVuY2lhcw0KDQpHYWJyaWVsIFVURUM6IE9TSVRSQU4gREFUQS4gKHMvZikuIEdvYi5wZTo4NDQzLiBSZWN1cGVyYWRvIGVsIDE3IGRlIGFicmlsIGRlIDIwMjMsIGRlIGh0dHBzOi8vc2VydmljaW9zZGlnaXRhbGVzLm9zaXRyYW4uZ29iLnBlOjg0NDMvUG9ydGFsRGF0b3NPc2l0cmFuL2luaWNpby5qc3ANCg0KDQpNZXphIEp1w6FyZXosIFYuIEEuICgyMDIwKS4gQVBBVklUIHkgdHVyaXNtbyBzZWd1cm8gcG9zdCBwYW5kZW1pYSBkZWwgQ292aWQtMTkgW1RyYWJham8gZGUgc3VmaWNpZW5jaWEgcHJvZmVzaW9uYWwgcGFyYSBvcHRhciBlbCBUw610dWxvIFByb2Zlc2lvbmFsIGRlIExpY2VuY2lhZG8gZW4gQ29tdW5pY2FjacOzbiwgVW5pdmVyc2lkYWQgZGUgTGltYV0uIFJlcG9zaXRvcmlvIEluc3RpdHVjaW9uYWwuIGh0dHBzOi8vaGRsLmhhbmRsZS5uZXQvMjAuNTAwLjEyNzI0LzExODEwDQoNCg0KQ3ViaWxsb3MsIEcuLCAmIEFsZWphbmRyYSwgTS4gKDIwMjIpLiBBbsOhbGlzaXMgZGUgbGEgQXBlcnR1cmEgZGUgbGEgRWNvbm9tw61hIFBvc3QgUGFuZGVtaWEgZW4gbG9zIFBhw61zZXMgTWllbWJyb3MgZGUgbGEgQWxpYW56YSBkZWwgUGFjw61maWNvICgyMDIwLTIwMjEpLiBodHRwOi8vcmVwb3NpdG9yeS51bmlwaWxvdG8uZWR1LmNvL2hhbmRsZS8yMC41MDAuMTIyNzcvMTE5ODANCg0KDQpWLiwgQ2FzdHJvIFPDoW5jaGV6LCBGLiwgJiBSb21lcm8gRmVybsOhbmRleiwgQS4gUi4gRi4gKDIwMjApLiBJbXBhY3RvIGRlIGxhIENPVklELTE5IGVuIGVsIHR1cmlzbW8gbXVuZGlhbCAoSW1wYWN0IG9mIENPVklELTE5IG9uIFdvcmxkIFRvdXJpc20pLiBodHRwczovL3BhcGVycy5zc3JuLmNvbS9hYnN0cmFjdD0zODE4Njg1